1522 lines
40 KiB
C
1522 lines
40 KiB
C
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ifmgr.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the interface management functions
|
|
|
|
Author:
|
|
|
|
Stefan Solomon 03/06/1995
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
//*** Interface Manager Globals ***
|
|
//
|
|
|
|
// Counter of existing interfaces
|
|
|
|
ULONG InterfaceCount = 0;
|
|
|
|
|
|
//
|
|
//*** Interface Manager APIs ***
|
|
//
|
|
|
|
typedef struct _IF_TYPE_TRANSLATION {
|
|
|
|
ROUTER_INTERFACE_TYPE DIMInterfaceType;
|
|
ULONG MIBInterfaceType;
|
|
|
|
} IF_TYPE_TRANSLATION, *PIF_TYPE_TRANSLATION;
|
|
|
|
IF_TYPE_TRANSLATION IfTypeTranslation[] = {
|
|
|
|
{ ROUTER_IF_TYPE_FULL_ROUTER, IF_TYPE_WAN_ROUTER },
|
|
{ ROUTER_IF_TYPE_HOME_ROUTER, IF_TYPE_PERSONAL_WAN_ROUTER },
|
|
{ ROUTER_IF_TYPE_DEDICATED, IF_TYPE_LAN },
|
|
{ ROUTER_IF_TYPE_CLIENT, IF_TYPE_WAN_WORKSTATION },
|
|
{ ROUTER_IF_TYPE_INTERNAL, IF_TYPE_INTERNAL }
|
|
|
|
};
|
|
|
|
#define MAX_IF_TRANSLATION_TYPES sizeof(IfTypeTranslation)/sizeof(IF_TYPE_TRANSLATION)
|
|
|
|
/*++
|
|
|
|
Function: AddInterface
|
|
|
|
Descr: Creates the interface control block and adds the specific
|
|
structures of the interface info to the corresponding modules.
|
|
|
|
Arguments:
|
|
InterfaceNamep :
|
|
|
|
Pointer to a WCHAR string representing the interface name.
|
|
|
|
InterfaceInfop :
|
|
|
|
Pointer to an IPX_INFO_BLOCK_HEADER structure containing the
|
|
IPX, RIP and SAP interface information, static routes and static services.
|
|
|
|
Pointer to an IPX_INFO_BLOCK_HEADER structure containing the
|
|
traffic filters.
|
|
|
|
InterfaceType:
|
|
|
|
REMARK: In order for the router to be able to start, the internal interface
|
|
has to be added.
|
|
|
|
--*/
|
|
|
|
DWORD
|
|
AddInterface(
|
|
IN LPWSTR InterfaceNamep,
|
|
IN LPVOID InterfaceInfop,
|
|
// IN LPVOID InFilterInfop,
|
|
// IN LPVOID OutFilterInfop,
|
|
IN ROUTER_INTERFACE_TYPE DIMInterfaceType,
|
|
IN HANDLE hDIMInterface,
|
|
IN OUT PHANDLE phInterface)
|
|
{
|
|
PICB icbp;
|
|
ULONG InterfaceNameLen; // if name length in bytes including wchar NULL
|
|
PIPX_IF_INFO IpxIfInfop;
|
|
PIPX_STATIC_ROUTE_INFO StaticRtInfop;
|
|
PIPX_STATIC_SERVICE_INFO StaticSvInfop;
|
|
PIPXWAN_IF_INFO IpxwanIfInfop;
|
|
PIPX_TRAFFIC_FILTER_GLOBAL_INFO InFltGlInfo, OutFltGlInfo;
|
|
// PUCHAR TrafficFilterInfop;
|
|
PIPX_INFO_BLOCK_HEADER IfInfop = (PIPX_INFO_BLOCK_HEADER)InterfaceInfop;
|
|
PACB acbp;
|
|
ULONG AdapterNameLen = 0; // length of adapter name
|
|
// for ROUTER_IF_TYPE_DEDICATED interface type.
|
|
PIPX_TOC_ENTRY tocep;
|
|
UINT i;
|
|
PIPX_ADAPTER_INFO AdapterInfop;
|
|
ULONG tmp;
|
|
FW_IF_INFO FwIfInfo;
|
|
PIF_TYPE_TRANSLATION ittp;
|
|
ULONG InterfaceIndex;
|
|
PIPX_STATIC_NETBIOS_NAME_INFO StaticNbInfop;
|
|
|
|
Trace(INTERFACE_TRACE, "AddInterface: Entered for interface %S", InterfaceNamep);
|
|
|
|
if(InterfaceInfop == NULL) {
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "AddInterface: Missing interface info for interface %ls\n", InterfaceNamep);
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
// interface name length including the unicode null
|
|
InterfaceNameLen = (wcslen(InterfaceNamep) + 1) * sizeof(WCHAR);
|
|
|
|
// If the interface type if ROUTER_IF_TYPE_DEDICATED (LAN Adapter) we parse the
|
|
// interface name to extract the adapter name and the packet type.
|
|
// The packet type will be then converted to an integer and the two will
|
|
// be used to identify a corresponding adapter.
|
|
|
|
if(DIMInterfaceType == ROUTER_IF_TYPE_DEDICATED) {
|
|
PWCHAR pszStart, pszEnd;
|
|
DWORD dwGuidLength = 37;
|
|
|
|
// get the lan adapter specific info from the interface
|
|
if((AdapterInfop = (PIPX_ADAPTER_INFO)GetInfoEntry(InterfaceInfop,
|
|
IPX_ADAPTER_INFO_TYPE)) == NULL)
|
|
{
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "AddInterface: Dedicated interface %ls missing adapter info\n", InterfaceNamep);
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// If the supplied adater is a reference to a guid, then use the name
|
|
// of the guid supplied in the interface name. This is because load/save
|
|
// config's can cause these two to get out of sync.
|
|
pszStart = wcsstr (InterfaceNamep, L"{");
|
|
pszEnd = wcsstr (InterfaceNamep, L"}");
|
|
if ( (pszStart) &&
|
|
(pszEnd) &&
|
|
(pszStart == InterfaceNamep) &&
|
|
((DWORD)(pszEnd - pszStart) == dwGuidLength) )
|
|
{
|
|
wcsncpy (AdapterInfop->AdapterName, InterfaceNamep, dwGuidLength);
|
|
}
|
|
|
|
AdapterNameLen = (wcslen(AdapterInfop->AdapterName) + 1) * sizeof(WCHAR);
|
|
}
|
|
|
|
ACQUIRE_DATABASE_LOCK;
|
|
|
|
if(RouterOperState != OPER_STATE_UP) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
// Check if this is the internal interface. If it is and if we
|
|
// already have the internal interface, we return an error
|
|
if((DIMInterfaceType == ROUTER_IF_TYPE_INTERNAL) &&
|
|
(InternalInterfacep)) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
// internal interface already exists
|
|
Trace(INTERFACE_TRACE, "AddInterface: INTERNAL interface already exists\n");
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Allocate a new ICB and initialize it
|
|
// we allocate the interface and adapter name buffers at the end of the
|
|
// ICB struct.
|
|
if((icbp = (PICB)GlobalAlloc(GPTR,
|
|
sizeof(ICB) +
|
|
InterfaceNameLen +
|
|
AdapterNameLen)) == NULL) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
// can't alloc memory
|
|
SS_ASSERT(FALSE);
|
|
|
|
return ERROR_OUT_OF_STRUCTURES;
|
|
}
|
|
|
|
// signature
|
|
memcpy(&icbp->Signature, InterfaceSignature, 4);
|
|
|
|
// get a new index and increment the global interface index counter
|
|
// if this is not the internal interface. For the internal interface we
|
|
// have reserved index 0
|
|
if(DIMInterfaceType == ROUTER_IF_TYPE_INTERNAL) {
|
|
|
|
icbp->InterfaceIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
icbp->InterfaceIndex = GetNextInterfaceIndex();
|
|
if(icbp->InterfaceIndex == MAX_INTERFACE_INDEX) {
|
|
|
|
GlobalFree(icbp);
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
}
|
|
|
|
InterfaceIndex = icbp->InterfaceIndex;
|
|
|
|
|
|
// copy the interface name
|
|
icbp->InterfaceNamep = (PWSTR)((PUCHAR)icbp + sizeof(ICB));
|
|
memcpy(icbp->InterfaceNamep, InterfaceNamep, InterfaceNameLen);
|
|
|
|
// copy the adapter name and packet type if dedicated interface
|
|
if(DIMInterfaceType == ROUTER_IF_TYPE_DEDICATED) {
|
|
|
|
icbp->AdapterNamep = (PWSTR)((PUCHAR)icbp + sizeof(ICB) + InterfaceNameLen);
|
|
wcscpy(icbp->AdapterNamep, AdapterInfop->AdapterName);
|
|
icbp->PacketType = AdapterInfop->PacketType;
|
|
}
|
|
else
|
|
{
|
|
icbp->AdapterNamep = NULL;
|
|
icbp->PacketType = 0;
|
|
}
|
|
|
|
// insert the if in the index hash table
|
|
AddIfToDB(icbp);
|
|
|
|
// get the if handle used when calling DIM entry points
|
|
icbp->hDIMInterface = hDIMInterface;
|
|
|
|
// reset the update status fields
|
|
ResetUpdateRequest(icbp);
|
|
|
|
// mark connection not requested yet
|
|
icbp->ConnectionRequestPending = FALSE;
|
|
|
|
// get to the interface entries in the interface info block
|
|
if(((IpxIfInfop = (PIPX_IF_INFO)GetInfoEntry(InterfaceInfop, IPX_INTERFACE_INFO_TYPE)) == NULL) ||
|
|
((IpxwanIfInfop = (PIPXWAN_IF_INFO)GetInfoEntry(InterfaceInfop, IPXWAN_INTERFACE_INFO_TYPE)) == NULL)) {
|
|
|
|
RemoveIfFromDB(icbp);
|
|
GlobalFree(icbp);
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
// don't have all ipx or ipxwan interfaces info
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "AddInterface: missing ipx or ipxwan interface info\n");
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Initialize the Admin State and the Oper State of this interface.
|
|
// Oper State may be changed will be changed later to OPER_STATE_SLEEPING
|
|
// if this is a WAN interface.
|
|
icbp->OperState = OPER_STATE_DOWN;
|
|
|
|
// set the DIM interface type of this ICB
|
|
icbp->DIMInterfaceType = DIMInterfaceType;
|
|
|
|
// set the MIB interface type of this ICB
|
|
icbp->MIBInterfaceType = IF_TYPE_OTHER;
|
|
for(i=0, ittp=IfTypeTranslation; i<MAX_IF_TRANSLATION_TYPES; i++, ittp++) {
|
|
|
|
if(icbp->DIMInterfaceType == ittp->DIMInterfaceType) {
|
|
|
|
icbp->MIBInterfaceType = ittp->MIBInterfaceType;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create the routing protocols (rip/sap or nlsp) interface info
|
|
// If the routing protocols interface info is missing this will fail
|
|
if(CreateRoutingProtocolsInterfaces(InterfaceInfop, icbp) != NO_ERROR) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
// don't have all rip and sap interfaces info
|
|
Trace(INTERFACE_TRACE, "AddInterface: Bad routing protocols interface config info\n");
|
|
|
|
goto ErrorExit;
|
|
}
|
|
|
|
// create the Forwarder interface
|
|
FwIfInfo.NetbiosAccept = IpxIfInfop->NetbiosAccept;
|
|
FwIfInfo.NetbiosDeliver = IpxIfInfop->NetbiosDeliver;
|
|
FwCreateInterface(icbp->InterfaceIndex,
|
|
MapIpxToNetInterfaceType(icbp),
|
|
&FwIfInfo);
|
|
|
|
// Seed the traffic filters
|
|
if ((tocep = GetTocEntry(InterfaceInfop, IPX_IN_TRAFFIC_FILTER_INFO_TYPE))!=NULL) {
|
|
|
|
if ((InFltGlInfo = GetInfoEntry(InterfaceInfop, IPX_IN_TRAFFIC_FILTER_GLOBAL_INFO_TYPE)) == NULL) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "AddInterface: Bad input filters config info");
|
|
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if (SetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_INBOUND,
|
|
InFltGlInfo->FilterAction, // pass or don't pass
|
|
tocep->InfoSize, // filter size
|
|
(LPBYTE)InterfaceInfop+tocep->Offset,
|
|
tocep->InfoSize*tocep->Count) != NO_ERROR) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "AddInterface: Bad input filters config info");
|
|
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
else { // No Filters -> delete all
|
|
if (SetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_INBOUND, // in or outbound,
|
|
0, // pass or don't pass
|
|
0, // filter size
|
|
NULL,
|
|
0)!=NO_ERROR) {
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
Trace(INTERFACE_TRACE, "AddInterface: Could not delete input filters");
|
|
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
if ((tocep = GetTocEntry(InterfaceInfop, IPX_OUT_TRAFFIC_FILTER_INFO_TYPE))!=NULL) {
|
|
|
|
if ((OutFltGlInfo = GetInfoEntry(InterfaceInfop, IPX_OUT_TRAFFIC_FILTER_GLOBAL_INFO_TYPE)) == NULL) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
Trace(INTERFACE_TRACE, "AddInterface: Bad output filters config info");
|
|
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if (SetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_OUTBOUND,
|
|
OutFltGlInfo->FilterAction, // pass or don't pass
|
|
tocep->InfoSize, // filter size
|
|
(LPBYTE)InterfaceInfop+tocep->Offset,
|
|
tocep->InfoSize*tocep->Count) != NO_ERROR) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "AddInterface: Bad output filters config info");
|
|
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
else { // No Filters -> delete all
|
|
if (SetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_OUTBOUND, // in or outbound,
|
|
0, // pass or don't pass
|
|
0, // filter size
|
|
NULL,
|
|
0)!=NO_ERROR) {
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
Trace(INTERFACE_TRACE, "AddInterface: Could not delete output filters");
|
|
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
// mark the interface reachable
|
|
icbp->InterfaceReachable = TRUE;
|
|
|
|
// set the admin state
|
|
if(IpxIfInfop->AdminState == ADMIN_STATE_ENABLED) {
|
|
|
|
AdminEnable(icbp);
|
|
}
|
|
else
|
|
{
|
|
AdminDisable(icbp);
|
|
}
|
|
|
|
// seed the static routes
|
|
if(DIMInterfaceType!=ROUTER_IF_TYPE_CLIENT) {
|
|
if (tocep = GetTocEntry(InterfaceInfop, IPX_STATIC_ROUTE_INFO_TYPE)) {
|
|
|
|
StaticRtInfop = (PIPX_STATIC_ROUTE_INFO)GetInfoEntry(InterfaceInfop,
|
|
IPX_STATIC_ROUTE_INFO_TYPE);
|
|
|
|
for(i=0; i<tocep->Count; i++, StaticRtInfop++) {
|
|
|
|
CreateStaticRoute(icbp, StaticRtInfop);
|
|
}
|
|
}
|
|
|
|
// seed the static services
|
|
if(tocep = GetTocEntry(InterfaceInfop, IPX_STATIC_SERVICE_INFO_TYPE)) {
|
|
|
|
StaticSvInfop = (PIPX_STATIC_SERVICE_INFO)GetInfoEntry(InterfaceInfop,
|
|
IPX_STATIC_SERVICE_INFO_TYPE);
|
|
|
|
for(i=0; i<tocep->Count; i++, StaticSvInfop++) {
|
|
|
|
CreateStaticService(icbp, StaticSvInfop);
|
|
}
|
|
}
|
|
|
|
// seed the static netbios names
|
|
if(tocep = GetTocEntry(InterfaceInfop, IPX_STATIC_NETBIOS_NAME_INFO_TYPE)) {
|
|
|
|
StaticNbInfop = (PIPX_STATIC_NETBIOS_NAME_INFO)GetInfoEntry(InterfaceInfop,
|
|
IPX_STATIC_NETBIOS_NAME_INFO_TYPE);
|
|
|
|
FwSetStaticNetbiosNames(icbp->InterfaceIndex,
|
|
tocep->Count,
|
|
StaticNbInfop);
|
|
}
|
|
}
|
|
|
|
// set the IPXWAN interface info
|
|
icbp->EnableIpxWanNegotiation = IpxwanIfInfop->AdminState;
|
|
|
|
// mark the interface as unbound to an adapter (default)
|
|
icbp->acbp = NULL;
|
|
|
|
// check if we can bind it now to an adapter. We can do this only for a
|
|
// a dedicated (LAN) interface or for an internal interface.
|
|
|
|
switch(icbp->DIMInterfaceType) {
|
|
|
|
case ROUTER_IF_TYPE_DEDICATED:
|
|
// Only bind interface if internal interface is already
|
|
// created and bound
|
|
if (InternalInterfacep && InternalInterfacep->acbp) {
|
|
// check if we have an adapter with a corresponding name and
|
|
// packet type
|
|
if((acbp = GetAdapterByNameAndPktType (icbp->AdapterNamep,
|
|
icbp->PacketType)) != NULL) {
|
|
|
|
BindInterfaceToAdapter(icbp, acbp);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case ROUTER_IF_TYPE_INTERNAL:
|
|
|
|
// get the pointer to the internal interface
|
|
InternalInterfacep = icbp;
|
|
|
|
// check that we have the adapter with adapter index 0 which
|
|
// represents the internal adapter
|
|
if(InternalAdapterp) {
|
|
PLIST_ENTRY lep;
|
|
acbp = InternalAdapterp;
|
|
|
|
BindInterfaceToAdapter(icbp, acbp);
|
|
lep = IndexIfList.Flink;
|
|
// Bind all previously added dedicated interfaces that were
|
|
// not bound awaiting for internal interface to be added
|
|
while(lep != &IndexIfList) {
|
|
PACB acbp2;
|
|
PICB icbp2 = CONTAINING_RECORD(lep, ICB, IndexListLinkage);
|
|
lep = lep->Flink;
|
|
switch(icbp2->DIMInterfaceType) {
|
|
case ROUTER_IF_TYPE_DEDICATED:
|
|
// check if we have an adapter with a corresponding name and
|
|
// packet type
|
|
if ((icbp2->acbp==NULL)
|
|
&&((acbp2 = GetAdapterByNameAndPktType (icbp2->AdapterNamep,
|
|
icbp2->PacketType)) != NULL)) {
|
|
|
|
BindInterfaceToAdapter(icbp2, acbp2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (icbp->AdminState==ADMIN_STATE_ENABLED)
|
|
// this is a WAN interface. As long as it isn't connected, and
|
|
// enabled the oper state will be sleeping on this interface
|
|
icbp->OperState = OPER_STATE_SLEEPING;
|
|
break;
|
|
|
|
}
|
|
|
|
// increment the interface counter
|
|
InterfaceCount++;
|
|
|
|
switch(icbp->DIMInterfaceType)
|
|
{
|
|
|
|
case ROUTER_IF_TYPE_DEDICATED:
|
|
|
|
if(icbp->acbp) {
|
|
|
|
Trace(INTERFACE_TRACE, "AddInterface: created LAN interface: # %d name %ls bound to adapter # %d name %ls\n",
|
|
icbp->InterfaceIndex,
|
|
icbp->InterfaceNamep,
|
|
icbp->acbp->AdapterIndex,
|
|
icbp->AdapterNamep);
|
|
}
|
|
else
|
|
{
|
|
Trace(INTERFACE_TRACE, "AddInterface: created LAN interface: # %d name %ls unbound to any adapter\n",
|
|
icbp->InterfaceIndex,
|
|
icbp->InterfaceNamep);
|
|
}
|
|
|
|
break;
|
|
|
|
case ROUTER_IF_TYPE_INTERNAL:
|
|
|
|
if(icbp->acbp) {
|
|
|
|
Trace(INTERFACE_TRACE, "AddInterface: created INTERNAL interface: # %d name %ls bound to internal adapter\n",
|
|
icbp->InterfaceIndex,
|
|
icbp->InterfaceNamep);
|
|
}
|
|
else
|
|
{
|
|
Trace(INTERFACE_TRACE, "AddInterface: created INTERNAL interface: # %d name %ls unbound to any adapter\n",
|
|
icbp->InterfaceIndex,
|
|
icbp->InterfaceNamep);
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Trace(INTERFACE_TRACE, "AddInterface: created WAN interface: # %d name %ls\n",
|
|
icbp->InterfaceIndex,
|
|
icbp->InterfaceNamep);
|
|
break;
|
|
|
|
}
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
// return the allocated if index
|
|
*phInterface = (HANDLE)UlongToPtr(icbp->InterfaceIndex);
|
|
return NO_ERROR;
|
|
|
|
ErrorExit:
|
|
|
|
InterfaceCount++;
|
|
|
|
DeleteInterface((HANDLE)UlongToPtr(InterfaceIndex));
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
/*++
|
|
|
|
Function: DeleteInterface
|
|
Descr:
|
|
|
|
--*/
|
|
|
|
DWORD
|
|
DeleteInterface(HANDLE InterfaceIndex)
|
|
{
|
|
PICB icbp;
|
|
|
|
Trace(INTERFACE_TRACE, "DeleteInterface: Entered for interface # %d\n",
|
|
InterfaceIndex);
|
|
|
|
ACQUIRE_DATABASE_LOCK;
|
|
|
|
if(RouterOperState != OPER_STATE_UP) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex));
|
|
|
|
if(icbp == NULL) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if(memcmp(&icbp->Signature, InterfaceSignature, 4)) {
|
|
|
|
// not a valid if pointer
|
|
SS_ASSERT(FALSE);
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// if bound to an adapter -> unbind
|
|
if(icbp->acbp) {
|
|
|
|
UnbindInterfaceFromAdapter(icbp);
|
|
}
|
|
|
|
// delete the routing protocols interfaces
|
|
DeleteRoutingProtocolsInterfaces(icbp->InterfaceIndex);
|
|
|
|
// delete all static routes from RTM
|
|
DeleteAllStaticRoutes(icbp->InterfaceIndex);
|
|
|
|
DeleteAllStaticServices(icbp->InterfaceIndex);
|
|
|
|
// delete the Fw interface. This will delete all associated filters
|
|
FwDeleteInterface(icbp->InterfaceIndex);
|
|
|
|
// remove the if from the data base
|
|
RemoveIfFromDB(icbp);
|
|
|
|
// done
|
|
GlobalFree(icbp);
|
|
|
|
// decrement the interface counter
|
|
InterfaceCount--;
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
Trace(INTERFACE_TRACE, "DeleteInterface: Deleted interface %d\n", InterfaceIndex);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Function: GetInterfaceInfo
|
|
Descr:
|
|
|
|
--*/
|
|
|
|
DWORD
|
|
GetInterfaceInfo(
|
|
IN HANDLE InterfaceIndex,
|
|
OUT LPVOID InterfaceInfop,
|
|
IN OUT DWORD *InterfaceInfoSize
|
|
// OUT LPVOID InFilterInfo,
|
|
// IN OUT DWORD *InFilterInfoSize,
|
|
// OUT LPVOID OutFilterInfo,
|
|
// IN OUT DWORD *OutFilterInfoSize
|
|
)
|
|
{
|
|
PICB icbp;
|
|
PIPX_INFO_BLOCK_HEADER ibhp, fbhp;
|
|
PIPX_TOC_ENTRY tocep;
|
|
PIPX_IF_INFO IpxIfInfop;
|
|
PIPX_STATIC_ROUTE_INFO StaticRtInfop;
|
|
PIPX_STATIC_SERVICE_INFO StaticSvInfop;
|
|
PIPXWAN_IF_INFO IpxwanIfInfop;
|
|
PIPX_ADAPTER_INFO IpxAdapterInfop;
|
|
PIPX_TRAFFIC_FILTER_GLOBAL_INFO InFltGlInfo, OutFltGlInfo;
|
|
ULONG InFltAction, OutFltAction;
|
|
ULONG InFltSize, OutFltSize;
|
|
ULONG InFltInfoSize=0, OutFltInfoSize=0;
|
|
FW_IF_STATS FwIfStats;
|
|
ULONG iftoccount = 0;
|
|
ULONG ifinfolen = 0;
|
|
ULONG NextInfoOffset;
|
|
ULONG IpxIfOffset = 0;
|
|
ULONG StaticRtOffset = 0;
|
|
ULONG StaticSvOffset = 0;
|
|
IPX_STATIC_ROUTE_INFO StaticRoute;
|
|
UINT i;
|
|
HANDLE EnumHandle;
|
|
FW_IF_INFO FwIfInfo;
|
|
ULONG StaticRoutesCount, StaticServicesCount, TrafficFiltersCount;
|
|
DWORD rc;
|
|
PIPX_STATIC_NETBIOS_NAME_INFO NetbiosNamesInfop;
|
|
ULONG NetbiosNamesCount = 0;
|
|
|
|
Trace(INTERFACE_TRACE, "GetInterfaceInfo: Entered for interface # %d\n", InterfaceIndex);
|
|
|
|
ACQUIRE_DATABASE_LOCK;
|
|
|
|
if(RouterOperState != OPER_STATE_UP) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
Trace(INTERFACE_TRACE, "GetInterfaceInfo: Nonexistent interface with # %d\n", InterfaceIndex);
|
|
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
SS_ASSERT(!memcmp(&icbp->Signature, InterfaceSignature, 4));
|
|
|
|
// calculate the minimum number of toc entries we should have:
|
|
// ipx toc entry
|
|
// routing protocols toc entries
|
|
// ipxwan toc entry
|
|
iftoccount = 2 + RoutingProtocolsTocCount();
|
|
|
|
// if this is a lan adapter, it should also have adapter info
|
|
if(icbp->DIMInterfaceType == ROUTER_IF_TYPE_DEDICATED) {
|
|
|
|
iftoccount++;
|
|
}
|
|
|
|
// calculate the minimun length of the interface info block
|
|
ifinfolen = sizeof(IPX_INFO_BLOCK_HEADER) +
|
|
(iftoccount - 1) * sizeof(IPX_TOC_ENTRY) +
|
|
sizeof(IPX_IF_INFO) +
|
|
SizeOfRoutingProtocolsIfsInfo(PtrToUlong(InterfaceIndex)) +
|
|
sizeof(IPXWAN_IF_INFO);
|
|
|
|
// if this is a lan adapter, add the size of the adapter info
|
|
if(icbp->DIMInterfaceType == ROUTER_IF_TYPE_DEDICATED) {
|
|
|
|
ifinfolen += sizeof(IPX_ADAPTER_INFO);
|
|
}
|
|
|
|
if(StaticRoutesCount = GetStaticRoutesCount(icbp->InterfaceIndex)) {
|
|
|
|
ifinfolen += sizeof(IPX_TOC_ENTRY) +
|
|
StaticRoutesCount * sizeof(IPX_STATIC_ROUTE_INFO);
|
|
|
|
iftoccount++;
|
|
}
|
|
|
|
if(StaticServicesCount = GetStaticServicesCount(icbp->InterfaceIndex)) {
|
|
|
|
ifinfolen += sizeof(IPX_TOC_ENTRY) +
|
|
StaticServicesCount * sizeof(IPX_STATIC_SERVICE_INFO);
|
|
|
|
iftoccount++;
|
|
}
|
|
|
|
FwGetStaticNetbiosNames(icbp->InterfaceIndex,
|
|
&NetbiosNamesCount,
|
|
NULL);
|
|
|
|
if(NetbiosNamesCount) {
|
|
|
|
ifinfolen += sizeof(IPX_TOC_ENTRY) +
|
|
NetbiosNamesCount * sizeof(IPX_STATIC_NETBIOS_NAME_INFO);
|
|
|
|
iftoccount++;
|
|
}
|
|
|
|
|
|
// get the length of the filters info
|
|
rc = GetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_INBOUND,
|
|
&InFltAction,
|
|
&InFltSize,
|
|
NULL,
|
|
&InFltInfoSize);
|
|
|
|
if((rc != NO_ERROR) && (rc != ERROR_INSUFFICIENT_BUFFER)) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return rc;
|
|
}
|
|
|
|
if (InFltInfoSize>0) {
|
|
ifinfolen += sizeof (IPX_TOC_ENTRY)*2 + InFltInfoSize
|
|
+ sizeof (IPX_TRAFFIC_FILTER_GLOBAL_INFO);
|
|
iftoccount += 2;
|
|
}
|
|
|
|
rc = GetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_OUTBOUND,
|
|
&OutFltAction,
|
|
&OutFltSize,
|
|
NULL,
|
|
&OutFltInfoSize);
|
|
|
|
if((rc != NO_ERROR) && (rc != ERROR_INSUFFICIENT_BUFFER)) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return rc;
|
|
}
|
|
|
|
if (OutFltInfoSize>0) {
|
|
ifinfolen += sizeof (IPX_TOC_ENTRY)*2 + OutFltInfoSize
|
|
+ sizeof (IPX_TRAFFIC_FILTER_GLOBAL_INFO);
|
|
iftoccount += 2;
|
|
}
|
|
// check if we have valid and sufficient buffers
|
|
if((InterfaceInfop == NULL) ||
|
|
(ifinfolen > *InterfaceInfoSize)) {
|
|
|
|
*InterfaceInfoSize = ifinfolen;
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
*InterfaceInfoSize = ifinfolen;
|
|
|
|
|
|
//
|
|
// Start filling in the interface info block
|
|
//
|
|
|
|
// start of the info block
|
|
ibhp = (PIPX_INFO_BLOCK_HEADER)InterfaceInfop;
|
|
|
|
// offset of the first INFO entry
|
|
NextInfoOffset = sizeof(IPX_INFO_BLOCK_HEADER) +
|
|
(iftoccount -1) * sizeof(IPX_TOC_ENTRY);
|
|
|
|
ibhp->Version = IPX_ROUTER_VERSION_1;
|
|
ibhp->Size = ifinfolen;
|
|
ibhp->TocEntriesCount = iftoccount;
|
|
|
|
tocep = ibhp->TocEntry;
|
|
|
|
// ipx if toc entry
|
|
tocep->InfoType = IPX_INTERFACE_INFO_TYPE;
|
|
tocep->InfoSize = sizeof(IPX_IF_INFO);
|
|
tocep->Count = 1;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
|
|
// ipx if info entry
|
|
IpxIfInfop = (PIPX_IF_INFO)((PUCHAR)ibhp + tocep->Offset);
|
|
|
|
IpxIfInfop->AdminState = icbp->AdminState;
|
|
|
|
FwGetInterface(icbp->InterfaceIndex,
|
|
&FwIfInfo,
|
|
&FwIfStats);
|
|
|
|
IpxIfInfop->NetbiosAccept = FwIfInfo.NetbiosAccept;
|
|
IpxIfInfop->NetbiosDeliver = FwIfInfo.NetbiosDeliver;
|
|
|
|
// create the toc and info entries for the routing protocols in the
|
|
// ouput buffer; this function will update the current TOC entry pointer
|
|
// value (tocep) and the current next entry info offset value (nextInfoOffset)
|
|
if((rc = CreateRoutingProtocolsTocAndInfoEntries(ibhp,
|
|
icbp->InterfaceIndex,
|
|
&tocep,
|
|
&NextInfoOffset)) != NO_ERROR) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return rc;
|
|
}
|
|
|
|
// ipxwan if toc entry
|
|
tocep++;
|
|
tocep->InfoType = IPXWAN_INTERFACE_INFO_TYPE;
|
|
tocep->InfoSize = sizeof(IPXWAN_IF_INFO);
|
|
tocep->Count = 1;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
|
|
// ipxwan if info entry
|
|
IpxwanIfInfop = (PIPXWAN_IF_INFO)((PUCHAR)ibhp + tocep->Offset);
|
|
|
|
IpxwanIfInfop->AdminState = icbp->EnableIpxWanNegotiation;
|
|
|
|
// if this is a lan interface, fill in the adapter info
|
|
if(icbp->DIMInterfaceType == ROUTER_IF_TYPE_DEDICATED) {
|
|
|
|
// ipx adapter toc entry
|
|
tocep++;
|
|
tocep->InfoType = IPX_ADAPTER_INFO_TYPE;
|
|
tocep->InfoSize = sizeof(IPX_ADAPTER_INFO);
|
|
|
|
tocep->Count = 1;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
|
|
// ipx adapter info entry
|
|
IpxAdapterInfop = (PIPX_ADAPTER_INFO)((PUCHAR)ibhp + tocep->Offset);
|
|
|
|
IpxAdapterInfop->PacketType = icbp->PacketType;
|
|
wcscpy(IpxAdapterInfop->AdapterName, icbp->AdapterNamep);
|
|
}
|
|
|
|
// static routes toc + info entries
|
|
if(StaticRoutesCount) {
|
|
|
|
// static routes toc entry
|
|
tocep++;
|
|
tocep->InfoType = IPX_STATIC_ROUTE_INFO_TYPE;
|
|
tocep->InfoSize = sizeof(IPX_STATIC_ROUTE_INFO);
|
|
tocep->Count = StaticRoutesCount;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
|
|
// Create static routes enumeration handle for this interface
|
|
EnumHandle = CreateStaticRoutesEnumHandle(icbp->InterfaceIndex);
|
|
|
|
for(i=0, StaticRtInfop = (PIPX_STATIC_ROUTE_INFO)((PUCHAR)ibhp + tocep->Offset);
|
|
i<StaticRoutesCount;
|
|
i++, StaticRtInfop++) {
|
|
|
|
GetNextStaticRoute(EnumHandle, StaticRtInfop);
|
|
}
|
|
|
|
// Close the enumeration handle
|
|
CloseStaticRoutesEnumHandle(EnumHandle);
|
|
}
|
|
|
|
// static services toc + info entries
|
|
if(StaticServicesCount) {
|
|
|
|
// static services toc entry
|
|
tocep++;
|
|
tocep->InfoType = IPX_STATIC_SERVICE_INFO_TYPE;
|
|
tocep->InfoSize = sizeof(IPX_STATIC_SERVICE_INFO);
|
|
tocep->Count = StaticServicesCount;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
|
|
// Create static services enumeration handle for this interface
|
|
EnumHandle = CreateStaticServicesEnumHandle(icbp->InterfaceIndex);
|
|
|
|
for(i=0, StaticSvInfop = (PIPX_STATIC_SERVICE_INFO)((PUCHAR)ibhp + tocep->Offset);
|
|
i<StaticServicesCount;
|
|
i++, StaticSvInfop++) {
|
|
|
|
GetNextStaticService(EnumHandle, StaticSvInfop);
|
|
}
|
|
|
|
// Close the enumeration handle
|
|
CloseStaticServicesEnumHandle(EnumHandle);
|
|
}
|
|
|
|
// static netbios names toc + info entries
|
|
if(NetbiosNamesCount) {
|
|
|
|
// static netbios names toc entry
|
|
tocep++;
|
|
tocep->InfoType = IPX_STATIC_NETBIOS_NAME_INFO_TYPE;
|
|
tocep->InfoSize = sizeof(IPX_STATIC_NETBIOS_NAME_INFO);
|
|
tocep->Count = NetbiosNamesCount;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
|
|
NetbiosNamesInfop = (PIPX_STATIC_NETBIOS_NAME_INFO)((PUCHAR)ibhp + tocep->Offset);
|
|
|
|
rc = FwGetStaticNetbiosNames(icbp->InterfaceIndex,
|
|
&NetbiosNamesCount,
|
|
NetbiosNamesInfop);
|
|
|
|
if(rc != NO_ERROR) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
if(InFltInfoSize) {
|
|
|
|
// traffic filter input global info
|
|
tocep++;
|
|
tocep->InfoType = IPX_IN_TRAFFIC_FILTER_GLOBAL_INFO_TYPE;
|
|
tocep->InfoSize = sizeof(IPX_TRAFFIC_FILTER_GLOBAL_INFO);
|
|
tocep->Count = 1;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
|
|
InFltGlInfo = (PIPX_TRAFFIC_FILTER_GLOBAL_INFO)((PUCHAR)ibhp + tocep->Offset);
|
|
|
|
|
|
rc = GetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_INBOUND,
|
|
&InFltAction,
|
|
&InFltSize,
|
|
(LPBYTE)InterfaceInfop+NextInfoOffset,
|
|
&InFltInfoSize);
|
|
if(rc != NO_ERROR) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return rc;
|
|
}
|
|
|
|
InFltGlInfo->FilterAction = InFltAction;
|
|
|
|
// traffic filter input global info
|
|
tocep++;
|
|
tocep->InfoType = IPX_IN_TRAFFIC_FILTER_INFO_TYPE;
|
|
tocep->InfoSize = InFltSize;
|
|
tocep->Count = InFltInfoSize/InFltSize;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
}
|
|
|
|
if(OutFltInfoSize) {
|
|
|
|
// traffic filter input global info
|
|
tocep++;
|
|
tocep->InfoType = IPX_OUT_TRAFFIC_FILTER_GLOBAL_INFO_TYPE;
|
|
tocep->InfoSize = sizeof(IPX_TRAFFIC_FILTER_GLOBAL_INFO);
|
|
tocep->Count = 1;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
|
|
OutFltGlInfo = (PIPX_TRAFFIC_FILTER_GLOBAL_INFO)((PUCHAR)ibhp + tocep->Offset);
|
|
|
|
|
|
rc = GetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_OUTBOUND,
|
|
&OutFltAction,
|
|
&OutFltSize,
|
|
(LPBYTE)InterfaceInfop+NextInfoOffset,
|
|
&OutFltInfoSize);
|
|
if(rc != NO_ERROR) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return rc;
|
|
}
|
|
|
|
OutFltGlInfo->FilterAction = OutFltAction;
|
|
|
|
// traffic filter input global info
|
|
tocep++;
|
|
tocep->InfoType = IPX_OUT_TRAFFIC_FILTER_INFO_TYPE;
|
|
tocep->InfoSize = OutFltSize;
|
|
tocep->Count = OutFltInfoSize/OutFltSize;
|
|
tocep->Offset = NextInfoOffset;
|
|
NextInfoOffset += tocep->Count * tocep->InfoSize;
|
|
}
|
|
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Function: SetInterfaceInfo
|
|
Descr:
|
|
|
|
--*/
|
|
|
|
|
|
DWORD
|
|
SetInterfaceInfo(
|
|
IN HANDLE InterfaceIndex,
|
|
IN LPVOID InterfaceInfop)
|
|
{
|
|
PICB icbp;
|
|
PIPX_IF_INFO IpxIfInfop;
|
|
PIPXWAN_IF_INFO IpxwanIfInfop;
|
|
PIPX_STATIC_ROUTE_INFO NewStaticRtInfop;
|
|
PIPX_STATIC_SERVICE_INFO NewStaticSvInfop;
|
|
PIPX_INFO_BLOCK_HEADER IfInfop = (PIPX_INFO_BLOCK_HEADER)InterfaceInfop;
|
|
PIPX_TOC_ENTRY tocep;
|
|
DWORD rc = NO_ERROR;
|
|
HANDLE EnumHandle;
|
|
FW_IF_INFO FwIfInfo;
|
|
PIPX_STATIC_NETBIOS_NAME_INFO StaticNbInfop;
|
|
PIPX_TRAFFIC_FILTER_GLOBAL_INFO InFltGlInfo, OutFltGlInfo;
|
|
|
|
ACQUIRE_DATABASE_LOCK;
|
|
|
|
if(RouterOperState != OPER_STATE_UP) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
|
|
if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
|
|
SS_ASSERT(!memcmp(&icbp->Signature, InterfaceSignature, 4));
|
|
|
|
// check if there was a change in the interface info block
|
|
if(IfInfop == NULL) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// check that we have all the mandatory info blocks
|
|
if(((IpxIfInfop = (PIPX_IF_INFO)GetInfoEntry(InterfaceInfop, IPX_INTERFACE_INFO_TYPE)) == NULL) ||
|
|
((IpxwanIfInfop = (PIPXWAN_IF_INFO)GetInfoEntry(InterfaceInfop, IPXWAN_INTERFACE_INFO_TYPE)) == NULL)) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
// invalid info
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if(SetRoutingProtocolsInterfaces(InterfaceInfop,
|
|
icbp->InterfaceIndex) != NO_ERROR) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
// invalid info
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// set ipx if info changes
|
|
if(icbp->AdminState != IpxIfInfop->AdminState) {
|
|
|
|
if(IpxIfInfop->AdminState == ADMIN_STATE_ENABLED) {
|
|
|
|
AdminEnable(icbp);
|
|
}
|
|
else
|
|
{
|
|
AdminDisable(icbp);
|
|
}
|
|
}
|
|
|
|
FwIfInfo.NetbiosAccept = IpxIfInfop->NetbiosAccept;
|
|
FwIfInfo.NetbiosDeliver = IpxIfInfop->NetbiosDeliver;
|
|
|
|
FwSetInterface(icbp->InterfaceIndex, &FwIfInfo);
|
|
|
|
// set IPXWAN info changes
|
|
icbp->EnableIpxWanNegotiation = IpxwanIfInfop->AdminState;
|
|
|
|
// set static routes
|
|
if((tocep = GetTocEntry(InterfaceInfop, IPX_STATIC_ROUTE_INFO_TYPE)) == NULL) {
|
|
|
|
// no static routes
|
|
// delete them if we've got them
|
|
if(GetStaticRoutesCount(icbp->InterfaceIndex)) {
|
|
|
|
DeleteAllStaticRoutes(icbp->InterfaceIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// delete non-present ones and add new ones
|
|
NewStaticRtInfop = (PIPX_STATIC_ROUTE_INFO)GetInfoEntry(InterfaceInfop, IPX_STATIC_ROUTE_INFO_TYPE);
|
|
|
|
// Create static routes enumeration handle for this interface
|
|
EnumHandle = CreateStaticRoutesEnumHandle(icbp->InterfaceIndex);
|
|
|
|
if(UpdateStaticIfEntries(icbp,
|
|
EnumHandle,
|
|
sizeof(IPX_STATIC_ROUTE_INFO),
|
|
tocep->Count, // number of routes in the new info
|
|
NewStaticRtInfop,
|
|
GetNextStaticRoute,
|
|
DeleteStaticRoute,
|
|
CreateStaticRoute)) {
|
|
|
|
// Close the enumeration handle
|
|
CloseStaticRoutesEnumHandle(EnumHandle);
|
|
|
|
rc = ERROR_GEN_FAILURE;
|
|
goto UpdateFailure;
|
|
}
|
|
|
|
// Close the enumeration handle
|
|
CloseStaticRoutesEnumHandle(EnumHandle);
|
|
}
|
|
|
|
// set static services
|
|
if((tocep = GetTocEntry(InterfaceInfop, IPX_STATIC_SERVICE_INFO_TYPE)) == NULL) {
|
|
|
|
// no static services
|
|
// delete them if we've got them
|
|
if(GetStaticServicesCount(icbp->InterfaceIndex)) {
|
|
|
|
DeleteAllStaticServices(icbp->InterfaceIndex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// delete non-present ones and add new ones
|
|
NewStaticSvInfop = (PIPX_STATIC_SERVICE_INFO)GetInfoEntry(InterfaceInfop, IPX_STATIC_SERVICE_INFO_TYPE);
|
|
|
|
// Create static services enumeration handle for this interface
|
|
EnumHandle = CreateStaticServicesEnumHandle(icbp->InterfaceIndex);
|
|
|
|
if(UpdateStaticIfEntries(icbp,
|
|
EnumHandle,
|
|
sizeof(IPX_STATIC_SERVICE_INFO),
|
|
tocep->Count, // number of services in the new info
|
|
NewStaticSvInfop,
|
|
GetNextStaticService,
|
|
DeleteStaticService,
|
|
CreateStaticService)) {
|
|
|
|
|
|
// Close the enumeration handle
|
|
CloseStaticServicesEnumHandle(EnumHandle);
|
|
|
|
rc = ERROR_GEN_FAILURE;
|
|
goto UpdateFailure;
|
|
}
|
|
|
|
// Close the enumeration handle
|
|
CloseStaticServicesEnumHandle(EnumHandle);
|
|
}
|
|
|
|
// set static netbios names
|
|
if((tocep = GetTocEntry(InterfaceInfop, IPX_STATIC_NETBIOS_NAME_INFO_TYPE)) == NULL) {
|
|
|
|
// no static netbios names
|
|
FwSetStaticNetbiosNames(icbp->InterfaceIndex,
|
|
0,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
// set the new ones
|
|
StaticNbInfop = (PIPX_STATIC_NETBIOS_NAME_INFO)GetInfoEntry(InterfaceInfop,
|
|
IPX_STATIC_NETBIOS_NAME_INFO_TYPE);
|
|
|
|
FwSetStaticNetbiosNames(icbp->InterfaceIndex,
|
|
tocep->Count,
|
|
StaticNbInfop);
|
|
}
|
|
|
|
// Seed the traffic filters
|
|
if ((tocep = GetTocEntry(InterfaceInfop, IPX_IN_TRAFFIC_FILTER_INFO_TYPE))!=NULL) {
|
|
|
|
if ((InFltGlInfo = GetInfoEntry(InterfaceInfop, IPX_IN_TRAFFIC_FILTER_GLOBAL_INFO_TYPE)) == NULL) {
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &icbp->InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "SetInterface: Bad input filters config info");
|
|
|
|
goto UpdateFailure;
|
|
}
|
|
|
|
if (SetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_INBOUND,
|
|
InFltGlInfo->FilterAction, // pass or don't pass
|
|
tocep->InfoSize, // filter size
|
|
(LPBYTE)InterfaceInfop+tocep->Offset,
|
|
tocep->InfoSize*tocep->Count) != NO_ERROR) {
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &icbp->InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "SetInterface: Bad input filters config info");
|
|
|
|
goto UpdateFailure;
|
|
}
|
|
}
|
|
else { // No Filters -> delete all
|
|
if (SetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_INBOUND, // in or outbound,
|
|
0, // pass or don't pass
|
|
0, // filter size
|
|
NULL,
|
|
0)!=NO_ERROR) {
|
|
|
|
Trace(INTERFACE_TRACE, "SetInterface: Could not delete input filters");
|
|
|
|
goto UpdateFailure;
|
|
}
|
|
}
|
|
|
|
if ((tocep = GetTocEntry(InterfaceInfop, IPX_OUT_TRAFFIC_FILTER_INFO_TYPE))!=NULL) {
|
|
|
|
if ((OutFltGlInfo = GetInfoEntry(InterfaceInfop, IPX_OUT_TRAFFIC_FILTER_GLOBAL_INFO_TYPE)) == NULL) {
|
|
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &icbp->InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "SetInterface: Bad output filters config info");
|
|
|
|
goto UpdateFailure;
|
|
}
|
|
|
|
if (SetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_OUTBOUND,
|
|
OutFltGlInfo->FilterAction, // pass or don't pass
|
|
tocep->InfoSize, // filter size
|
|
(LPBYTE)InterfaceInfop+tocep->Offset,
|
|
tocep->InfoSize*tocep->Count) != NO_ERROR) {
|
|
|
|
IF_LOG (EVENTLOG_ERROR_TYPE) {
|
|
RouterLogErrorDataW (RMEventLogHdl,
|
|
ROUTERLOG_IPX_BAD_INTERFACE_CONFIG,
|
|
1, &icbp->InterfaceNamep, 0, NULL);
|
|
}
|
|
Trace(INTERFACE_TRACE, "SetInterface: Bad output filters config info");
|
|
|
|
goto UpdateFailure;
|
|
}
|
|
}
|
|
else { // No Filters -> delete all
|
|
if (SetFilters(icbp->InterfaceIndex,
|
|
IPX_TRAFFIC_FILTER_OUTBOUND, // in or outbound,
|
|
0, // pass or don't pass
|
|
0, // filter size
|
|
NULL,
|
|
0)!=NO_ERROR) {
|
|
Trace(INTERFACE_TRACE, "SetInterface: Could not delete output filters");
|
|
|
|
goto UpdateFailure;
|
|
}
|
|
}
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
return NO_ERROR;
|
|
|
|
UpdateFailure:
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return rc;
|
|
}
|
|
|
|
/*++
|
|
|
|
Function: InterfaceNotReachable
|
|
|
|
Descr: Called in the following cases:
|
|
|
|
1. Following a ConnectInterface request from the Router Manager,
|
|
to indicate that the connection atempt has failed.
|
|
|
|
2. When DIM realizes it won't be able to execute any further
|
|
ConnectInterface requests because of out of resources.
|
|
|
|
--*/
|
|
|
|
DWORD
|
|
InterfaceNotReachable(
|
|
IN HANDLE InterfaceIndex,
|
|
IN UNREACHABILITY_REASON Reason)
|
|
{
|
|
PICB icbp;
|
|
|
|
Trace(INTERFACE_TRACE, "IpxRM: InterfaceNotReachable: Entered for if # %d\n",
|
|
InterfaceIndex);
|
|
|
|
ACQUIRE_DATABASE_LOCK;
|
|
|
|
if(RouterOperState != OPER_STATE_UP) {
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
|
|
if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
|
|
|
|
// interface has been removed
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if(icbp->ConnectionRequestPending) {
|
|
|
|
icbp->ConnectionRequestPending = FALSE;
|
|
|
|
// notify the forwarder of the connection failure
|
|
FwConnectionRequestFailed(icbp->InterfaceIndex);
|
|
}
|
|
|
|
// if there is reason to stop advertising routes/services on this if
|
|
// because it can't be reached in the future, do it!
|
|
|
|
if(icbp->InterfaceReachable)
|
|
{
|
|
icbp->InterfaceReachable = FALSE;
|
|
|
|
// stop advertising static routes on this interface
|
|
DisableStaticRoutes(icbp->InterfaceIndex);
|
|
|
|
// disable the interface for all routing prot and fw
|
|
// this will stop advertising any static services
|
|
ExternalDisableInterface(icbp->InterfaceIndex);
|
|
}
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*++
|
|
|
|
Function: InterfaceReachable
|
|
|
|
Descr: Called by DIM following a previous InterfaceNotReachable to
|
|
indicate that conditions are met to do connections on this if.
|
|
|
|
--*/
|
|
|
|
DWORD
|
|
InterfaceReachable(
|
|
IN HANDLE InterfaceIndex)
|
|
{
|
|
PICB icbp;
|
|
|
|
Trace(INTERFACE_TRACE, "IpxRM: InterfaceReachable: Entered for if # %d\n",
|
|
InterfaceIndex);
|
|
|
|
ACQUIRE_DATABASE_LOCK;
|
|
if(RouterOperState != OPER_STATE_UP) {
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
|
|
|
|
// interface has been removed
|
|
RELEASE_DATABASE_LOCK;
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if(!icbp->InterfaceReachable) {
|
|
|
|
icbp->InterfaceReachable = TRUE;
|
|
|
|
if(icbp->AdminState == ADMIN_STATE_ENABLED) {
|
|
|
|
// enable all static routes for this interface
|
|
EnableStaticRoutes(icbp->InterfaceIndex);
|
|
|
|
// enable external interfaces. Implicitly, this will enable static services
|
|
// bound to this interface to be advertised
|
|
ExternalEnableInterface(icbp->InterfaceIndex);
|
|
}
|
|
}
|
|
|
|
RELEASE_DATABASE_LOCK;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD APIENTRY
|
|
InterfaceConnected (
|
|
IN HANDLE hInterface,
|
|
IN PVOID pFilter,
|
|
IN PVOID pPppProjectionResult
|
|
) {
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
DestroyAllInterfaces(VOID)
|
|
{
|
|
PICB icbp;
|
|
|
|
while(!IsListEmpty(&IndexIfList)) {
|
|
|
|
icbp = CONTAINING_RECORD(IndexIfList.Flink, ICB, IndexListLinkage);
|
|
|
|
// remove the if from the data base
|
|
RemoveIfFromDB(icbp);
|
|
|
|
Trace(INTERFACE_TRACE, "DestroyAllInterfaces: destroyed interface %d\n", icbp->InterfaceIndex);
|
|
|
|
GlobalFree(icbp);
|
|
|
|
// decrement the interface counter
|
|
InterfaceCount--;
|
|
}
|
|
}
|