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 ();
|
||
}
|
||
|
||
|