329 lines
8.8 KiB
C
329 lines
8.8 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
ntos\tdi\isn\fwd\lineind.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
Processing line indication (bind/unbind)
|
|||
|
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Vadim Eydelman
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
*******************************************************************
|
|||
|
B i n d I n t e r f a c e
|
|||
|
|
|||
|
Routine Description:
|
|||
|
Binds interface to physical adapter and exchanges contexts
|
|||
|
with IPX stack
|
|||
|
Arguments:
|
|||
|
ifCB - interface to bind
|
|||
|
NicId - id of an adapter
|
|||
|
MaxPacketSize - max size of packet allowed
|
|||
|
Network - adapter network address
|
|||
|
LocalNode - adapter local node address
|
|||
|
RemoteNode - peer node address (for clients on global
|
|||
|
net)
|
|||
|
Return Value:
|
|||
|
STATUS_SUCCESS - interface was bound OK
|
|||
|
error status returned by IPX stack driver
|
|||
|
|
|||
|
*******************************************************************
|
|||
|
--*/
|
|||
|
NTSTATUS
|
|||
|
BindInterface (
|
|||
|
IN PINTERFACE_CB ifCB,
|
|||
|
IN USHORT NicId,
|
|||
|
IN ULONG MaxPacketSize,
|
|||
|
IN ULONG Network,
|
|||
|
IN PUCHAR LocalNode,
|
|||
|
IN PUCHAR RemoteNode
|
|||
|
) {
|
|||
|
KIRQL oldIRQL;
|
|||
|
NTSTATUS status;
|
|||
|
NIC_HANDLE NicHandle={0};
|
|||
|
|
|||
|
KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
|
|||
|
if (ifCB->ICB_Stats.OperationalState!=FWD_OPER_STATE_UP) {
|
|||
|
switch (ifCB->ICB_InterfaceType) {
|
|||
|
case FWD_IF_PERMANENT:
|
|||
|
if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX)
|
|||
|
status = RegisterPacketConsumer (MaxPacketSize,
|
|||
|
&ifCB->ICB_PacketListId);
|
|||
|
else
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
case FWD_IF_DEMAND_DIAL:
|
|||
|
case FWD_IF_LOCAL_WORKSTATION:
|
|||
|
case FWD_IF_REMOTE_WORKSTATION:
|
|||
|
if (IS_IF_CONNECTING (ifCB)) {
|
|||
|
SET_IF_NOT_CONNECTING (ifCB);
|
|||
|
DequeueConnectionRequest (ifCB);
|
|||
|
}
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
default:
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
ASSERTMSG ("Invalid interface type ", FALSE);
|
|||
|
break;
|
|||
|
}
|
|||
|
if (NT_SUCCESS (status)) {
|
|||
|
if (Network==GlobalNetwork) {
|
|||
|
ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
|
|||
|
IPX_NODE_CPY (ifCB->ICB_RemoteNode, RemoteNode);
|
|||
|
status = AddGlobalNetClient (ifCB);
|
|||
|
ASSERT (status==STATUS_SUCCESS);
|
|||
|
}
|
|||
|
KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
|
|||
|
|
|||
|
if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX) {
|
|||
|
NIC_HANDLE_FROM_NIC(NicHandle, NicId);
|
|||
|
status = IPXOpenAdapterProc (NicHandle, (ULONG_PTR)ifCB,
|
|||
|
&ifCB->ICB_AdapterContext);
|
|||
|
}
|
|||
|
|
|||
|
if (NT_SUCCESS (status)) {
|
|||
|
ifCB->ICB_Network = Network;
|
|||
|
IPX_NODE_CPY (ifCB->ICB_RemoteNode, RemoteNode);
|
|||
|
IPX_NODE_CPY (ifCB->ICB_LocalNode, LocalNode);
|
|||
|
if (ifCB->ICB_InterfaceType==FWD_IF_PERMANENT)
|
|||
|
ifCB->ICB_Stats.MaxPacketSize = MaxPacketSize;
|
|||
|
else
|
|||
|
ifCB->ICB_Stats.MaxPacketSize = WAN_PACKET_SIZE;
|
|||
|
ifCB->ICB_NicId = NicId;
|
|||
|
ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_UP;
|
|||
|
|
|||
|
AcquireInterfaceReference (ifCB);
|
|||
|
IpxFwdDbgPrint (DBG_LINEIND, DBG_INFORMATION,
|
|||
|
("IpxFwd: Bound interface %ld (icb: %08lx):"
|
|||
|
" Nic-%d, Net-%08lx,"
|
|||
|
" LocalNode-%02x%02x%02x%02x%02x%02x,"
|
|||
|
" RemoteNode-%02x%02x%02x%02x%02x%02x.\n",
|
|||
|
ifCB->ICB_Index, ifCB, NicId, Network,
|
|||
|
LocalNode[0], LocalNode[1], LocalNode[2],
|
|||
|
LocalNode[3], LocalNode[4], LocalNode[5],
|
|||
|
RemoteNode[0], RemoteNode[1], RemoteNode[2],
|
|||
|
RemoteNode[3], RemoteNode[4], RemoteNode[5]));
|
|||
|
|
|||
|
if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX) {
|
|||
|
ProcessInternalQueue (ifCB);
|
|||
|
ProcessExternalQueue (ifCB);
|
|||
|
}
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
IpxFwdDbgPrint (DBG_LINEIND, DBG_ERROR,
|
|||
|
("IpxFwd: Could not open adapter %d to bind"
|
|||
|
" interface %ld (icb: %08lx)!\n",
|
|||
|
NicId, ifCB->ICB_Index, ifCB));
|
|||
|
|
|||
|
KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
|
|||
|
if (Network==GlobalNetwork) {
|
|||
|
DeleteGlobalNetClient (ifCB);
|
|||
|
}
|
|||
|
|
|||
|
switch (ifCB->ICB_InterfaceType) {
|
|||
|
case FWD_IF_PERMANENT:
|
|||
|
DeregisterPacketConsumer (ifCB->ICB_PacketListId);
|
|||
|
break;
|
|||
|
case FWD_IF_DEMAND_DIAL:
|
|||
|
case FWD_IF_LOCAL_WORKSTATION:
|
|||
|
case FWD_IF_REMOTE_WORKSTATION:
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_DOWN;
|
|||
|
KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
|
|||
|
|
|||
|
ProcessInternalQueue (ifCB);
|
|||
|
ProcessExternalQueue (ifCB);
|
|||
|
}
|
|||
|
else {
|
|||
|
ASSERT (Network==ifCB->ICB_Network);
|
|||
|
ASSERT (NicId==(USHORT)ifCB->ICB_AdapterContext.NicId);
|
|||
|
KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
|
|||
|
status = STATUS_SUCCESS; // Report success if already
|
|||
|
// connected
|
|||
|
IpxFwdDbgPrint (DBG_LINEIND, DBG_WARNING,
|
|||
|
("IpxFwd: Interface %ld (icb: %08lx) is already bound to Nic %d.\n",
|
|||
|
ifCB->ICB_Index, ifCB, NicId));
|
|||
|
}
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
*******************************************************************
|
|||
|
U n b i n d I n t e r f a c e
|
|||
|
|
|||
|
Routine Description:
|
|||
|
Unbinds interface from physical adapter and breaks connection
|
|||
|
with IPX stack
|
|||
|
Arguments:
|
|||
|
ifCB - interface to unbind
|
|||
|
Return Value:
|
|||
|
None
|
|||
|
*******************************************************************
|
|||
|
--*/
|
|||
|
VOID
|
|||
|
UnbindInterface (
|
|||
|
PINTERFACE_CB ifCB
|
|||
|
) {
|
|||
|
KIRQL oldIRQL;
|
|||
|
KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
|
|||
|
if (ifCB->ICB_Stats.OperationalState==FWD_OPER_STATE_UP) {
|
|||
|
switch (ifCB->ICB_InterfaceType) {
|
|||
|
case FWD_IF_PERMANENT:
|
|||
|
ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_DOWN;
|
|||
|
if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX)
|
|||
|
DeregisterPacketConsumer (ifCB->ICB_PacketListId);
|
|||
|
break;
|
|||
|
case FWD_IF_DEMAND_DIAL:
|
|||
|
case FWD_IF_LOCAL_WORKSTATION:
|
|||
|
case FWD_IF_REMOTE_WORKSTATION:
|
|||
|
ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_SLEEPING;
|
|||
|
KeQuerySystemTime ((PLARGE_INTEGER)&ifCB->ICB_DisconnectTime);
|
|||
|
break;
|
|||
|
default:
|
|||
|
ASSERTMSG ("Invalid interface type ", FALSE);
|
|||
|
break;
|
|||
|
}
|
|||
|
if (ifCB->ICB_CashedInterface!=NULL)
|
|||
|
ReleaseInterfaceReference (ifCB->ICB_CashedInterface);
|
|||
|
ifCB->ICB_CashedInterface = NULL;
|
|||
|
if (ifCB->ICB_CashedRoute!=NULL)
|
|||
|
ReleaseRouteReference (ifCB->ICB_CashedRoute);
|
|||
|
ifCB->ICB_CashedRoute = NULL;
|
|||
|
if (ifCB->ICB_Network==GlobalNetwork)
|
|||
|
DeleteGlobalNetClient (ifCB);
|
|||
|
KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
|
|||
|
|
|||
|
IpxFwdDbgPrint (DBG_LINEIND, DBG_INFORMATION,
|
|||
|
("IpxFwd: Unbinding interface %ld (icb: %08lx) from Nic %ld.\n",
|
|||
|
ifCB->ICB_Index, ifCB, ifCB->ICB_AdapterContext));
|
|||
|
if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX) {
|
|||
|
// [pmay]. Because of pnp, this interface may not need to have an
|
|||
|
// adapter closed any more. This is because nic id's get renumbered.
|
|||
|
if (ifCB->ICB_NicId != INVALID_NIC_ID)
|
|||
|
IPXCloseAdapterProc (ifCB->ICB_AdapterContext);
|
|||
|
ProcessInternalQueue (ifCB);
|
|||
|
ProcessExternalQueue (ifCB);
|
|||
|
}
|
|||
|
ReleaseInterfaceReference (ifCB);
|
|||
|
}
|
|||
|
else {
|
|||
|
KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
|
|||
|
IpxFwdDbgPrint (DBG_LINEIND, DBG_WARNING,
|
|||
|
("IpxFwd: Interface %ld (icb: %08lx) is already unbound.\n",
|
|||
|
ifCB->ICB_Index, ifCB));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
*******************************************************************
|
|||
|
F w L i n e U p
|
|||
|
|
|||
|
Routine Description:
|
|||
|
Process line up indication delivered by IPX stack
|
|||
|
Arguments:
|
|||
|
NicId - adapter ID on which connection was established
|
|||
|
LineInfo - NDIS/IPX line information
|
|||
|
DeviceType - medium specs
|
|||
|
ConfigurationData - IPX CP configuration data
|
|||
|
Return Value:
|
|||
|
None
|
|||
|
|
|||
|
*******************************************************************
|
|||
|
--*/
|
|||
|
VOID
|
|||
|
IpxFwdLineUp (
|
|||
|
IN USHORT NicId,
|
|||
|
IN PIPX_LINE_INFO LineInfo,
|
|||
|
IN NDIS_MEDIUM DeviceType,
|
|||
|
IN PVOID ConfigurationData
|
|||
|
) {
|
|||
|
PINTERFACE_CB ifCB;
|
|||
|
if (ConfigurationData==NULL) // This is just an update for multilink
|
|||
|
// connections
|
|||
|
return;
|
|||
|
|
|||
|
if (!EnterForwarder()) {
|
|||
|
return;
|
|||
|
}
|
|||
|
IpxFwdDbgPrint (DBG_LINEIND, DBG_INFORMATION, ("IpxFwd: FwdLineUp.\n"));
|
|||
|
|
|||
|
ifCB = GetInterfaceReference (
|
|||
|
((PIPXCP_CONFIGURATION)ConfigurationData)->InterfaceIndex);
|
|||
|
if (ifCB!=NULL) {
|
|||
|
LONG Net = GETULONG (((PIPXCP_CONFIGURATION)ConfigurationData)->Network);
|
|||
|
|
|||
|
ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
|
|||
|
ASSERT (ifCB->ICB_InterfaceType!=FWD_IF_PERMANENT);
|
|||
|
|
|||
|
BindInterface (ifCB,
|
|||
|
NicId,
|
|||
|
LineInfo->MaximumPacketSize,
|
|||
|
Net,
|
|||
|
((PIPXCP_CONFIGURATION)ConfigurationData)->LocalNode,
|
|||
|
((PIPXCP_CONFIGURATION)ConfigurationData)->RemoteNode
|
|||
|
);
|
|||
|
ReleaseInterfaceReference (ifCB);
|
|||
|
}
|
|||
|
LeaveForwarder ();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
*******************************************************************
|
|||
|
F w L i n e D o w n
|
|||
|
|
|||
|
Routine Description:
|
|||
|
Process line down indication delivered by IPX stack
|
|||
|
Arguments:
|
|||
|
NicId - disconnected adapter ID
|
|||
|
Return Value:
|
|||
|
None
|
|||
|
|
|||
|
*******************************************************************
|
|||
|
--*/
|
|||
|
VOID
|
|||
|
IpxFwdLineDown (
|
|||
|
IN USHORT NicId,
|
|||
|
IN ULONG_PTR Context
|
|||
|
) {
|
|||
|
PINTERFACE_CB ifCB;
|
|||
|
|
|||
|
if (!EnterForwarder()) {
|
|||
|
return;
|
|||
|
}
|
|||
|
IpxFwdDbgPrint (DBG_LINEIND, DBG_INFORMATION, ("IpxFwd: FwdLineDown.\n"));
|
|||
|
|
|||
|
|
|||
|
ifCB = InterfaceContextToReference ((PVOID)Context, NicId);
|
|||
|
if (ifCB!=NULL) {
|
|||
|
ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
|
|||
|
ASSERT (ifCB->ICB_InterfaceType!=FWD_IF_PERMANENT);
|
|||
|
UnbindInterface (ifCB);
|
|||
|
ReleaseInterfaceReference (ifCB);
|
|||
|
}
|
|||
|
LeaveForwarder ();
|
|||
|
}
|
|||
|
|
|||
|
|