You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
937 lines
21 KiB
937 lines
21 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
D:\nt\private\ntos\tdi\rawwan\core\addr.c
|
|
|
|
Abstract:
|
|
|
|
TDI Entry points and support routines for Address Objects.
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----------------------------------------------
|
|
arvindm 04-29-97 Created
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
|
|
#define _FILENUMBER 'RDDA'
|
|
|
|
|
|
//
|
|
// Context we use to keep track of NDIS SAP registration
|
|
//
|
|
typedef struct _RWAN_REGISTER_SAP_CONTEXT
|
|
{
|
|
PRWAN_NDIS_SAP pRWanNdisSap;
|
|
CO_SAP CoSap;
|
|
|
|
} RWAN_REGISTER_SAP_CONTEXT, *PRWAN_REGISTER_SAP_CONTEXT;
|
|
|
|
|
|
|
|
|
|
TDI_STATUS
|
|
RWanTdiOpenAddress(
|
|
IN PTDI_REQUEST pTdiRequest,
|
|
IN TRANSPORT_ADDRESS UNALIGNED *pAddrList,
|
|
IN ULONG AddrListLength,
|
|
IN UINT Protocol,
|
|
IN PUCHAR pOptions
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the TDI entry point for opening (creating) an Address Object.
|
|
|
|
Arguments:
|
|
|
|
pTdiRequest - Pointer to the TDI Request
|
|
pAddrList - List of alternative addresses, one of which we're to open.
|
|
AddrListLength - Length of the above
|
|
Protocol - Identifies the TDI Protocol being opened.
|
|
pOptions - Unused.
|
|
|
|
Return Value:
|
|
|
|
TDI_STATUS -- TDI_SUCCESS if a new Address Object was successfully
|
|
created, TDI_BAD_ADDR if the given address isn't valid,
|
|
TDI_ADDR_IN_USE if it is a duplicate.
|
|
|
|
--*/
|
|
{
|
|
PRWAN_TDI_PROTOCOL pProtocol;
|
|
PRWAN_TDI_ADDRESS pAddrObject;
|
|
TA_ADDRESS * pTransportAddress;
|
|
TDI_STATUS Status;
|
|
INT rc;
|
|
|
|
UNREFERENCED_PARAMETER(pOptions);
|
|
|
|
//
|
|
// Initialize.
|
|
//
|
|
pAddrObject = NULL_PRWAN_TDI_ADDRESS;
|
|
Status = TDI_SUCCESS;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Get our protocol structure for the protocol being opened.
|
|
//
|
|
pProtocol = RWanGetProtocolFromNumber(Protocol);
|
|
if (pProtocol == NULL_PRWAN_TDI_PROTOCOL)
|
|
{
|
|
RWANDEBUGP(DL_WARN, DC_ADDRESS,
|
|
("RWanTdiOpenAddress: unknown protocol number %d\n", Protocol));
|
|
Status = TDI_BAD_ADDR;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Does this protocol allow creation of address objects?
|
|
//
|
|
if (!pProtocol->bAllowAddressObjects)
|
|
{
|
|
RWANDEBUGP(DL_WARN, DC_ADDRESS,
|
|
("RWanTdiOpenAddress: Protocol %d/x%x doesn't allow addr objs\n",
|
|
Protocol, pProtocol));
|
|
Status = TDI_BAD_ADDR;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Go through the given Address list and find the first one
|
|
// that matches the protocol.
|
|
//
|
|
pTransportAddress = (*pProtocol->pAfInfo->AfChars.pAfSpGetValidTdiAddress)(
|
|
pProtocol->pAfInfo->AfSpContext,
|
|
pAddrList,
|
|
AddrListLength
|
|
);
|
|
|
|
if (pTransportAddress == NULL)
|
|
{
|
|
RWANDEBUGP(DL_WARN, DC_ADDRESS,
|
|
("RWanTdiOpenAddress: No valid addr for Protocol x%x in list x%x\n",
|
|
pProtocol, pAddrList));
|
|
Status = TDI_BAD_ADDR;
|
|
break;
|
|
}
|
|
|
|
|
|
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
|
|
("RWanTdiOpenAddress: pProto x%x, addr x%x, type %d, length %d\n",
|
|
pProtocol,
|
|
pTransportAddress,
|
|
pTransportAddress->AddressType,
|
|
pTransportAddress->AddressLength));
|
|
|
|
|
|
//
|
|
// Allocate an Address Object.
|
|
//
|
|
pAddrObject = RWanAllocateAddressObject(pTransportAddress);
|
|
|
|
if (pAddrObject == NULL_PRWAN_TDI_ADDRESS)
|
|
{
|
|
RWANDEBUGP(DL_WARN, DC_ADDRESS,
|
|
("RWanTdiOpenAddress: couldnt allocate addr obj: %d bytes\n",
|
|
sizeof(RWAN_TDI_ADDRESS)+pTransportAddress->AddressLength));
|
|
|
|
Status = TDI_NO_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
pAddrObject->pProtocol = pProtocol;
|
|
|
|
|
|
//
|
|
// Get a context for this address object from the media-specific
|
|
// module.
|
|
//
|
|
if (pAddrObject->pProtocol->pAfInfo->AfChars.pAfSpOpenAddress)
|
|
{
|
|
RWAN_STATUS RWanStatus;
|
|
|
|
RWanStatus = (*pAddrObject->pProtocol->pAfInfo->AfChars.pAfSpOpenAddress)(
|
|
pAddrObject->pProtocol->pAfInfo->AfSpContext,
|
|
(RWAN_HANDLE)pAddrObject,
|
|
&(pAddrObject->AfSpAddrContext));
|
|
|
|
if (RWanStatus != RWAN_STATUS_SUCCESS)
|
|
{
|
|
Status = RWanToTdiStatus(RWanStatus);
|
|
break;
|
|
}
|
|
|
|
RWAN_SET_BIT(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID);
|
|
}
|
|
|
|
|
|
RWAN_ACQUIRE_ADDRESS_LIST_LOCK();
|
|
|
|
|
|
//
|
|
// If this is a non-NULL address, register NDIS SAPs on all
|
|
// AF bindings for this protocol.
|
|
//
|
|
if (!((*pProtocol->pAfInfo->AfChars.pAfSpIsNullAddress)(
|
|
pProtocol->pAfInfo->AfSpContext,
|
|
pTransportAddress)))
|
|
{
|
|
//
|
|
// Add a temp ref so that the address object doesn't go away.
|
|
//
|
|
RWanReferenceAddressObject(pAddrObject); // TdiOpenAddress temp ref
|
|
|
|
Status = RWanCreateNdisSaps(pAddrObject, pProtocol);
|
|
|
|
if (Status != TDI_SUCCESS)
|
|
{
|
|
if (RWAN_IS_BIT_SET(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID))
|
|
{
|
|
(*pAddrObject->pProtocol->pAfInfo->AfChars.pAfSpCloseAddress)(
|
|
pAddrObject->AfSpAddrContext);
|
|
|
|
RWAN_RESET_BIT(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get rid of the temp reference.
|
|
//
|
|
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
|
|
rc = RWanDereferenceAddressObject(pAddrObject); // TdiOpenAddr temp ref
|
|
|
|
if (rc != 0)
|
|
{
|
|
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The address object is gone. Meaning no SAPs got registered.
|
|
//
|
|
pAddrObject = NULL;
|
|
|
|
//
|
|
// Fix up the status only if we haven't got one already.
|
|
//
|
|
if (Status == TDI_SUCCESS)
|
|
{
|
|
Status = TDI_BAD_ADDR;
|
|
}
|
|
}
|
|
|
|
if (Status != TDI_SUCCESS)
|
|
{
|
|
RWAN_RELEASE_ADDRESS_LIST_LOCK();
|
|
break;
|
|
}
|
|
}
|
|
|
|
RWAN_ASSERT(pAddrObject != NULL);
|
|
|
|
RWanReferenceAddressObject(pAddrObject); // TdiOpenAddress ref
|
|
|
|
//
|
|
// Link this to the list of address objects on this protocol.
|
|
//
|
|
RWAN_INSERT_HEAD_LIST(&(pProtocol->AddrObjList),
|
|
&(pAddrObject->AddrLink));
|
|
|
|
RWAN_RELEASE_ADDRESS_LIST_LOCK();
|
|
|
|
//
|
|
// Fix up all return values.
|
|
//
|
|
pTdiRequest->Handle.AddressHandle = (PVOID)pAddrObject;
|
|
break;
|
|
|
|
}
|
|
while (FALSE);
|
|
|
|
|
|
if (Status != TDI_SUCCESS)
|
|
{
|
|
//
|
|
// Clean up.
|
|
//
|
|
if (pAddrObject != NULL_PRWAN_TDI_ADDRESS)
|
|
{
|
|
RWAN_FREE_MEM(pAddrObject);
|
|
}
|
|
RWANDEBUGP(DL_FATAL, DC_WILDCARD,
|
|
("OpenAddr: failure status %x\n", Status));
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
|
|
|
|
TDI_STATUS
|
|
RWanTdiSetEvent(
|
|
IN PVOID AddrObjContext,
|
|
IN INT TdiEventType,
|
|
IN PVOID Handler,
|
|
IN PVOID HandlerContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set an event handler (up-call) for an address object.
|
|
|
|
Arguments:
|
|
|
|
AddrObjContext - Our context for an Address Object (pointer to it).
|
|
TdiEventType - The TDI Event for which we are given an up-call handler.
|
|
Handler - The handler function
|
|
HandlerContext - Context to be passed to the handler function.
|
|
|
|
Return Value:
|
|
|
|
TDI_STATUS - TDI_SUCCESS if the event type is a supported one, else
|
|
TDI_BAD_EVENT_TYPE
|
|
|
|
--*/
|
|
{
|
|
PRWAN_TDI_ADDRESS pAddrObject;
|
|
TDI_STATUS Status;
|
|
|
|
pAddrObject = (PRWAN_TDI_ADDRESS)AddrObjContext;
|
|
RWAN_STRUCT_ASSERT(pAddrObject, nta);
|
|
|
|
Status = TDI_SUCCESS;
|
|
|
|
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
|
|
|
|
switch (TdiEventType)
|
|
{
|
|
case TDI_EVENT_CONNECT:
|
|
|
|
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
|
|
("SetEvent[CONN IND]: pAddrObject x%x, Handler x%x, Ctxt x%x\n",
|
|
pAddrObject, Handler, HandlerContext));
|
|
|
|
pAddrObject->pConnInd = Handler;
|
|
pAddrObject->ConnIndContext = HandlerContext;
|
|
break;
|
|
|
|
case TDI_EVENT_DISCONNECT:
|
|
|
|
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
|
|
("SetEvent[DISC IND]: pAddrObject x%x, Handler x%x, Ctxt x%x\n",
|
|
pAddrObject, Handler, HandlerContext));
|
|
|
|
pAddrObject->pDisconInd = Handler;
|
|
pAddrObject->DisconIndContext = HandlerContext;
|
|
break;
|
|
|
|
case TDI_EVENT_ERROR:
|
|
|
|
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
|
|
("SetEvent[ERRORIND]: pAddrObject x%x, Handler x%x, Ctxt x%x\n",
|
|
pAddrObject, Handler, HandlerContext));
|
|
|
|
pAddrObject->pErrorInd = Handler;
|
|
pAddrObject->ErrorIndContext = HandlerContext;
|
|
break;
|
|
|
|
case TDI_EVENT_RECEIVE:
|
|
|
|
RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
|
|
("SetEvent[RECV IND]: pAddrObject x%x, Handler x%x, Ctxt x%x\n",
|
|
pAddrObject, Handler, HandlerContext));
|
|
|
|
pAddrObject->pRcvInd = Handler;
|
|
pAddrObject->RcvIndContext = HandlerContext;
|
|
break;
|
|
|
|
default:
|
|
|
|
Status = TDI_BAD_EVENT_TYPE;
|
|
break;
|
|
}
|
|
|
|
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
|
|
|
|
TDI_STATUS
|
|
RWanTdiCloseAddress(
|
|
IN PTDI_REQUEST pTdiRequest
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the TDI entry point for closing (deleting) an Address Object.
|
|
|
|
Arguments:
|
|
|
|
pTdiRequest - Pointer to the TDI Request
|
|
|
|
Return Value:
|
|
|
|
TDI_STATUS -- TDI_SUCCESS if we successfully deleted the address
|
|
object immediately, TDI_PENDING if we have to complete some operations
|
|
(e.g. deregister NDIS SAP) before we can complete this.
|
|
|
|
--*/
|
|
{
|
|
TDI_STATUS Status;
|
|
PRWAN_TDI_ADDRESS pAddrObject;
|
|
PRWAN_TDI_PROTOCOL pProtocol;
|
|
INT rc;
|
|
#if DBG
|
|
RWAN_IRQL EntryIrq, ExitIrq;
|
|
#endif // DBG
|
|
|
|
RWAN_GET_ENTRY_IRQL(EntryIrq);
|
|
|
|
pAddrObject = (PRWAN_TDI_ADDRESS)pTdiRequest->Handle.AddressHandle;
|
|
RWAN_STRUCT_ASSERT(pAddrObject, nta);
|
|
|
|
pProtocol = pAddrObject->pProtocol;
|
|
|
|
RWANDEBUGP(DL_EXTRA_LOUD, DC_BIND,
|
|
("TdiCloseAddr: pAddrObj x%x, RefCnt %d\n",
|
|
pAddrObject, pAddrObject->RefCount));
|
|
|
|
//
|
|
// Delete this from the list of address objects on this protocol.
|
|
//
|
|
RWAN_ACQUIRE_ADDRESS_LIST_LOCK();
|
|
|
|
RWAN_DELETE_FROM_LIST(&(pAddrObject->AddrLink));
|
|
|
|
RWAN_RELEASE_ADDRESS_LIST_LOCK();
|
|
|
|
//
|
|
// Tell the media-specific module that this address object is closing.
|
|
//
|
|
if (RWAN_IS_BIT_SET(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID))
|
|
{
|
|
(*pAddrObject->pProtocol->pAfInfo->AfChars.pAfSpCloseAddress)(
|
|
pAddrObject->AfSpAddrContext);
|
|
|
|
RWAN_RESET_BIT(pAddrObject->Flags, RWANF_AO_AFSP_CONTEXT_VALID);
|
|
}
|
|
|
|
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
|
|
|
|
#if DBG
|
|
if (!RWAN_IS_LIST_EMPTY(&pAddrObject->SapList) ||
|
|
!RWAN_IS_LIST_EMPTY(&pAddrObject->IdleConnList) ||
|
|
!RWAN_IS_LIST_EMPTY(&pAddrObject->ListenConnList) ||
|
|
!RWAN_IS_LIST_EMPTY(&pAddrObject->ActiveConnList)
|
|
)
|
|
{
|
|
RWAN_ASSERT(pAddrObject->RefCount > 1);
|
|
}
|
|
#endif // DBG
|
|
|
|
rc = RWanDereferenceAddressObject(pAddrObject); // CloseAddress deref
|
|
|
|
if (rc == 0)
|
|
{
|
|
Status = TDI_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Mark this address object as closing, so that we
|
|
// complete this operation when the reference count
|
|
// falls to 0.
|
|
//
|
|
RWAN_SET_BIT(pAddrObject->Flags, RWANF_AO_CLOSING);
|
|
|
|
RWANDEBUGP(DL_LOUD, DC_BIND,
|
|
("TdiCloseAddr: will pend, pAddrObj x%x, RefCnt %d, DelNotify x%x\n",
|
|
pAddrObject, pAddrObject->RefCount, pTdiRequest->RequestNotifyObject));
|
|
|
|
RWAN_SET_DELETE_NOTIFY(&pAddrObject->DeleteNotify,
|
|
pTdiRequest->RequestNotifyObject,
|
|
pTdiRequest->RequestContext);
|
|
|
|
//
|
|
// Deregister all NDIS SAPs attached to this Address Object.
|
|
//
|
|
RWanDeleteNdisSaps(pAddrObject);
|
|
|
|
Status = TDI_PENDING;
|
|
}
|
|
|
|
RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
|
|
|
|
return (Status);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TDI_STATUS
|
|
RWanCreateNdisSaps(
|
|
IN PRWAN_TDI_ADDRESS pAddrObject,
|
|
IN PRWAN_TDI_PROTOCOL pProtocol
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create NDIS SAPs on behalf of the given TDI Address Object.
|
|
We create NDIS SAPs on all AF opens that match the specified
|
|
TDI protocol.
|
|
|
|
Arguments:
|
|
|
|
pAddrObject - Pointer to our TDI Address Object
|
|
pProtocol - Pointer to TDI protocol to which the addr object belongs
|
|
|
|
Return Value:
|
|
|
|
TDI_STATUS -- this is TDI_SUCCESS if we started SAP registration
|
|
on atleast one NDIS AF open, TDI_NOT_ASSOCIATED otherwise.
|
|
|
|
--*/
|
|
{
|
|
TDI_STATUS Status;
|
|
PCO_SAP pCoSap;
|
|
PRWAN_NDIS_SAP pSap;
|
|
PLIST_ENTRY pSapEntry;
|
|
PLIST_ENTRY pNextSapEntry;
|
|
PRWAN_NDIS_ADAPTER pAdapter;
|
|
PLIST_ENTRY pAdEntry;
|
|
PRWAN_NDIS_AF pAf;
|
|
PLIST_ENTRY pAfEntry;
|
|
PRWAN_NDIS_AF_INFO pAfInfo;
|
|
|
|
pAfInfo = pProtocol->pAfInfo;
|
|
|
|
RWANDEBUGP(DL_VERY_LOUD, DC_BIND,
|
|
("CreateNdisSaps: pAddrObject x%x, pProtocol x%x, pAfInfo x%x\n",
|
|
pAddrObject, pProtocol, pAfInfo));
|
|
|
|
RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pAddrObject->SapList));
|
|
|
|
RWAN_ACQUIRE_GLOBAL_LOCK();
|
|
|
|
//
|
|
// Prepare NDIS SAP structures for each NDIS AF open that matches
|
|
// this protocol.
|
|
//
|
|
for (pAdEntry = pRWanGlobal->AdapterList.Flink;
|
|
pAdEntry != &(pRWanGlobal->AdapterList);
|
|
pAdEntry = pAdEntry->Flink)
|
|
{
|
|
pAdapter = CONTAINING_RECORD(pAdEntry, RWAN_NDIS_ADAPTER, AdapterLink);
|
|
|
|
RWANDEBUGP(DL_EXTRA_LOUD, DC_BIND,
|
|
("CreateNdisSaps: looking at adapter x%x\n", pAdapter));
|
|
|
|
for (pAfEntry = pAdapter->AfList.Flink;
|
|
pAfEntry != &(pAdapter->AfList);
|
|
pAfEntry = pAfEntry->Flink)
|
|
{
|
|
pAf = CONTAINING_RECORD(pAfEntry, RWAN_NDIS_AF, AfLink);
|
|
|
|
RWANDEBUGP(DL_EXTRA_LOUD, DC_BIND,
|
|
("CreateNdisSaps: looking at AF x%x, AfInfo x%x\n",
|
|
pAf, pAf->pAfInfo));
|
|
|
|
if (pAf->pAfInfo == pAfInfo)
|
|
{
|
|
//
|
|
// This NDIS AF open matches the TDI protocol for which
|
|
// the address object is opened. We will create an NDIS
|
|
// SAP here.
|
|
//
|
|
|
|
ULONG SapSize;
|
|
|
|
//
|
|
// Allocate a new SAP structure.
|
|
//
|
|
SapSize = sizeof(RWAN_NDIS_SAP);
|
|
|
|
RWAN_ALLOC_MEM(pSap, RWAN_NDIS_SAP, SapSize);
|
|
|
|
if (pSap == NULL_PRWAN_NDIS_SAP)
|
|
{
|
|
RWANDEBUGP(DL_WARN, DC_ADDRESS,
|
|
("RWanCreateNdisSaps: failed to alloc SAP %d bytes\n",
|
|
SapSize));
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Fill it in.
|
|
//
|
|
RWAN_SET_SIGNATURE(pSap, nsp);
|
|
pSap->pAddrObject = pAddrObject;
|
|
pSap->NdisSapHandle = NULL;
|
|
pSap->pNdisAf = pAf;
|
|
pSap->pCoSap = NULL;
|
|
|
|
//
|
|
// Link to all SAPs associated with address object.
|
|
//
|
|
RWAN_INSERT_TAIL_LIST(&(pAddrObject->SapList),
|
|
&(pSap->AddrObjLink));
|
|
|
|
RWanReferenceAddressObject(pAddrObject); // NDIS SAP ref
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
RWAN_RELEASE_GLOBAL_LOCK();
|
|
|
|
//
|
|
// Now go through the SAP list and call NDIS to register them.
|
|
//
|
|
for (pSapEntry = pAddrObject->SapList.Flink;
|
|
pSapEntry != &(pAddrObject->SapList);
|
|
pSapEntry = pNextSapEntry)
|
|
{
|
|
RWAN_STATUS RWanStatus;
|
|
NDIS_STATUS NdisStatus;
|
|
|
|
pSap = CONTAINING_RECORD(pSapEntry, RWAN_NDIS_SAP, AddrObjLink);
|
|
pNextSapEntry = pSap->AddrObjLink.Flink;
|
|
|
|
//
|
|
// Convert the transport address to NDIS SAP format.
|
|
//
|
|
RWanStatus = (*pAfInfo->AfChars.pAfSpTdi2NdisSap)(
|
|
pAfInfo->AfSpContext,
|
|
pAddrObject->AddressType,
|
|
pAddrObject->AddressLength,
|
|
pAddrObject->pAddress,
|
|
&(pSap->pCoSap));
|
|
|
|
|
|
if (RWanStatus == RWAN_STATUS_SUCCESS)
|
|
{
|
|
RWAN_ASSERT(pSap->pCoSap != NULL);
|
|
|
|
//
|
|
// Register this SAP with the Call Manager.
|
|
//
|
|
NdisStatus = NdisClRegisterSap(
|
|
pSap->pNdisAf->NdisAfHandle,
|
|
(NDIS_HANDLE)pSap,
|
|
pSap->pCoSap,
|
|
&(pSap->NdisSapHandle)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
NdisStatus = NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
if (NdisStatus != NDIS_STATUS_PENDING)
|
|
{
|
|
RWanNdisRegisterSapComplete(
|
|
NdisStatus,
|
|
(NDIS_HANDLE)pSap,
|
|
pSap->pCoSap,
|
|
pSap->NdisSapHandle
|
|
);
|
|
|
|
}
|
|
}
|
|
|
|
if (!RWAN_IS_LIST_EMPTY(&pAddrObject->SapList))
|
|
{
|
|
Status = TDI_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Status = RWanNdisToTdiStatus(pAddrObject->SapStatus);
|
|
RWANDEBUGP(DL_WARN, DC_WILDCARD,
|
|
("CreateNdisSaps: NdisStatus %x, TdiStatus %x\n",
|
|
pAddrObject->SapStatus, Status));
|
|
}
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
RWanNdisRegisterSapComplete(
|
|
IN NDIS_STATUS NdisStatus,
|
|
IN NDIS_HANDLE OurSapContext,
|
|
IN PCO_SAP pCoSap,
|
|
IN NDIS_HANDLE NdisSapHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is called by NDIS to signal completion of a previously
|
|
pended call to NdisClRegisterSap.
|
|
|
|
Arguments:
|
|
|
|
NdisStatus - Final status of SAP registration.
|
|
OurSapContext - Points to our NDIS SAP structure.
|
|
pCoSap - The parameter we passed to NdisClRegisterSap. Not used.
|
|
NdisSapHandle - If NdisStatus indicates success, this contains the
|
|
assigned handle for this SAP.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PRWAN_NDIS_SAP pSap;
|
|
PRWAN_TDI_ADDRESS pAddrObject;
|
|
INT rc;
|
|
PRWAN_NDIS_AF_INFO pAfInfo;
|
|
PRWAN_NDIS_AF pAf;
|
|
|
|
UNREFERENCED_PARAMETER(pCoSap);
|
|
|
|
pSap = (PRWAN_NDIS_SAP)OurSapContext;
|
|
RWAN_STRUCT_ASSERT(pSap, nsp);
|
|
|
|
pAddrObject = pSap->pAddrObject;
|
|
|
|
pAfInfo = pSap->pNdisAf->pAfInfo;
|
|
pCoSap = pSap->pCoSap;
|
|
pSap->pCoSap = NULL;
|
|
|
|
RWANDEBUGP(DL_LOUD, DC_BIND,
|
|
("RegisterSapComplete: pAddrObj x%x, pSap x%x, Status x%x\n",
|
|
pAddrObject, pSap, NdisStatus));
|
|
|
|
if (NdisStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
pSap->NdisSapHandle = NdisSapHandle;
|
|
pAf = pSap->pNdisAf;
|
|
|
|
//
|
|
// Link this SAP to the list of all SAPs on the AF.
|
|
//
|
|
RWAN_ACQUIRE_AF_LOCK(pAf);
|
|
|
|
RWAN_INSERT_TAIL_LIST(&pAf->NdisSapList,
|
|
&pSap->AfLink);
|
|
|
|
RWanReferenceAf(pAf); // New SAP registered.
|
|
|
|
RWAN_RELEASE_AF_LOCK(pAf);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Failed to register this SAP. Clean up.
|
|
//
|
|
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
|
|
|
|
pAddrObject->SapStatus = NdisStatus;
|
|
|
|
RWAN_DELETE_FROM_LIST(&(pSap->AddrObjLink));
|
|
|
|
rc = RWanDereferenceAddressObject(pAddrObject); // Reg SAP failed
|
|
|
|
if (rc != 0)
|
|
{
|
|
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
|
|
}
|
|
|
|
RWAN_FREE_MEM(pSap);
|
|
}
|
|
|
|
//
|
|
// If the AF-specific module had given us a SAP structure,
|
|
// return it now.
|
|
//
|
|
if (pCoSap != NULL)
|
|
{
|
|
(*pAfInfo->AfChars.pAfSpReturnNdisSap)(
|
|
pAfInfo->AfSpContext,
|
|
pCoSap
|
|
);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
RWanDeleteNdisSaps(
|
|
IN PRWAN_TDI_ADDRESS pAddrObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete all NDIS SAPs on the given address object. We call NDIS
|
|
to deregister them.
|
|
|
|
Arguments:
|
|
|
|
pAddrObject - Pointer to TDI Address Object
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PRWAN_NDIS_SAP pSap;
|
|
PLIST_ENTRY pSapEntry;
|
|
PLIST_ENTRY pFirstSapEntry;
|
|
PLIST_ENTRY pNextSapEntry;
|
|
NDIS_STATUS NdisStatus;
|
|
NDIS_HANDLE NdisSapHandle;
|
|
|
|
//
|
|
// Mark all SAPs as closing, while we hold a lock to the address object.
|
|
//
|
|
for (pSapEntry = pAddrObject->SapList.Flink;
|
|
pSapEntry != &(pAddrObject->SapList);
|
|
pSapEntry = pNextSapEntry)
|
|
{
|
|
pSap = CONTAINING_RECORD(pSapEntry, RWAN_NDIS_SAP, AddrObjLink);
|
|
pNextSapEntry = pSap->AddrObjLink.Flink;
|
|
RWAN_SET_BIT(pSap->Flags, RWANF_SAP_CLOSING);
|
|
}
|
|
|
|
//
|
|
// Unlink the SAP list from the Address Object.
|
|
// This will protect us if at all we re-enter this routine.
|
|
//
|
|
pFirstSapEntry = pAddrObject->SapList.Flink;
|
|
RWAN_INIT_LIST(&pAddrObject->SapList);
|
|
|
|
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
|
|
|
|
for (pSapEntry = pFirstSapEntry;
|
|
pSapEntry != &(pAddrObject->SapList);
|
|
pSapEntry = pNextSapEntry)
|
|
{
|
|
pSap = CONTAINING_RECORD(pSapEntry, RWAN_NDIS_SAP, AddrObjLink);
|
|
pNextSapEntry = pSap->AddrObjLink.Flink;
|
|
|
|
NdisSapHandle = pSap->NdisSapHandle;
|
|
RWAN_ASSERT(NdisSapHandle != NULL);
|
|
|
|
RWANDEBUGP(DL_LOUD, DC_BIND,
|
|
("RWanDeleteNdisSaps: pAddrObj x%x, pSap x%x, pAf x%x\n",
|
|
pAddrObject, pSap, pSap->pNdisAf));
|
|
|
|
NdisStatus = NdisClDeregisterSap(NdisSapHandle);
|
|
|
|
if (NdisStatus != NDIS_STATUS_PENDING)
|
|
{
|
|
RWanNdisDeregisterSapComplete(
|
|
NdisStatus,
|
|
(NDIS_HANDLE)pSap
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
RWanNdisDeregisterSapComplete(
|
|
IN NDIS_STATUS NdisStatus,
|
|
IN NDIS_HANDLE ProtocolSapContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is called by NDIS to signal completion of a previously
|
|
pended call to NdisClDeregisterSap.
|
|
|
|
We unlink the SAP from the two lists it is linked to: the
|
|
Address Object's SAP list and the AF's SAP list.
|
|
|
|
Arguments:
|
|
|
|
NdisStatus - Final status of SAP deregistration.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PRWAN_NDIS_SAP pSap;
|
|
PRWAN_TDI_ADDRESS pAddrObject;
|
|
PRWAN_NDIS_AF pAf;
|
|
INT rc;
|
|
|
|
RWAN_ASSERT(NdisStatus == NDIS_STATUS_SUCCESS);
|
|
|
|
pSap = (PRWAN_NDIS_SAP)ProtocolSapContext;
|
|
RWAN_STRUCT_ASSERT(pSap, nsp);
|
|
|
|
RWANDEBUGP(DL_VERY_LOUD, DC_BIND,
|
|
("RWanDeregSapComplete: pSap x%x, pAddrObj x%x, pAf x%x\n",
|
|
pSap, pSap->pAddrObject, pSap->pNdisAf));
|
|
|
|
pAddrObject = pSap->pAddrObject;
|
|
|
|
//
|
|
// Unlink the SAP from the Address Object.
|
|
//
|
|
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
|
|
|
|
RWAN_DELETE_FROM_LIST(&(pSap->AddrObjLink));
|
|
|
|
rc = RWanDereferenceAddressObject(pAddrObject); // SAP dereg complete
|
|
|
|
if (rc != 0)
|
|
{
|
|
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
|
|
}
|
|
|
|
//
|
|
// Unlink the SAP from the AF.
|
|
//
|
|
pAf = pSap->pNdisAf;
|
|
|
|
RWAN_STRUCT_ASSERT(pAf, naf);
|
|
|
|
RWAN_ACQUIRE_AF_LOCK(pAf);
|
|
|
|
RWAN_DELETE_FROM_LIST(&(pSap->AfLink));
|
|
|
|
rc = RWanDereferenceAf(pAf); // SAP deregister complete
|
|
|
|
if (rc != 0)
|
|
{
|
|
RWAN_RELEASE_AF_LOCK(pAf);
|
|
}
|
|
|
|
RWAN_FREE_MEM(pSap);
|
|
}
|