|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
connreq.c
Abstract:
This module contains the connection request handling functions
Author:
Stefan Solomon 04/19/1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
VOID DoConnectInterface(PVOID InterfaceIndex);
/*++
Function: ForwarderNotification
Descr: This is invoked in the router manager worker thread context following a notification from the forwarder. It dequeues all connection requests and calls DDM for each one of them.
--*/
VOID ForwarderNotification(VOID) { DWORD rc; PICB icbp; HANDLE hDIMInterface; ULONG nBytes = 0;
// Check if the signaled notification is valid or an error condition
rc = FwGetNotificationResult(&ConnReqOverlapped, &nBytes);
ACQUIRE_DATABASE_LOCK; if (RouterOperState == OPER_STATE_UP) { if(rc == NO_ERROR) { if (((icbp = GetInterfaceByIndex(ConnRequest->IfIndex)) != NULL) && !icbp->ConnectionRequestPending) { IF_LOG (EVENTLOG_INFORMATION_TYPE) { WCHAR ByteCount[16]; LPWSTR StrArray[2]= {icbp->InterfaceNamep, ByteCount};
_ultow (nBytes-FIELD_OFFSET (FW_DIAL_REQUEST, Packet), ByteCount, 10); RouterLogInformationDataW (RMEventLogHdl, ROUTERLOG_IPX_DEMAND_DIAL_PACKET, 2, StrArray, nBytes-FIELD_OFFSET (FW_DIAL_REQUEST, Packet), &ConnRequest->Packet[0]); }
icbp->ConnectionRequestPending = TRUE; if(RtlQueueWorkItem(DoConnectInterface, (PVOID)ConnRequest, 0) == STATUS_SUCCESS) {
// work item queued
WorkItemsPendingCounter++; } else { SS_ASSERT(FALSE); } ConnRequest = (PFW_DIAL_REQUEST)GlobalAlloc (GPTR, DIAL_REQUEST_BUFFER_SIZE); if (ConnRequest==NULL) { rc = GetLastError (); Trace(CONNREQ_TRACE, "Cannot allocate Connecttion Request buffer, rc = %d\n", rc); } } } else { Trace(CONNREQ_TRACE, "Error %d in FwGetNotificationResult\n", rc); } // now repost the IOCtl
if (ConnRequest!=NULL) { rc = FwNotifyConnectionRequest(ConnRequest, DIAL_REQUEST_BUFFER_SIZE, &ConnReqOverlapped);
if(rc != NO_ERROR) { GlobalFree (ConnRequest); ConnRequest = NULL; Trace(CONNREQ_TRACE, "Cannot repost the FwNotifyConnecttionRequest, rc = %d\n", rc); } } } else { GlobalFree (ConnRequest); } RELEASE_DATABASE_LOCK; return; }
VOID DoConnectInterface(PVOID param) { #define connRequest ((PFW_DIAL_REQUEST)param)
PICB icbp; HANDLE hDIMInterface; DWORD rc;
ACQUIRE_DATABASE_LOCK;
if(RouterOperState != OPER_STATE_UP) {
goto Exit; }
if ((icbp = GetInterfaceByIndex(connRequest->IfIndex)) == NULL){ goto Exit; }
hDIMInterface = icbp->hDIMInterface;
RELEASE_DATABASE_LOCK;
rc = (*ConnectInterface)(hDIMInterface, PID_IPX);
ACQUIRE_DATABASE_LOCK;
if((icbp = GetInterfaceByIndex(connRequest->IfIndex)) == NULL) {
goto Exit; }
if (rc != PENDING) { icbp->ConnectionRequestPending = FALSE;
// check if we failed right away
if(rc != NO_ERROR) {
// failed to request connection
Trace(CONNREQ_TRACE, "DoConnectInterface: ConnectInterface failed with rc= 0x%x for if # %d\n", rc, connRequest->IfIndex);
FwConnectionRequestFailed(connRequest->IfIndex); } else { // Connection request has been succesfull right away and
// we will get notified via the connected adapter
Trace(CONNREQ_TRACE, "DoConnectInterface: ConnectInterface successful -> CONNECTED for if # %d\n", connRequest->IfIndex); } } else { // a connection request is pending
Trace(CONNREQ_TRACE, "DoConnectInterface: Connection request PENDING for if # %d\n", connRequest->IfIndex);
}
Exit: GlobalFree (connRequest); WorkItemsPendingCounter--;
RELEASE_DATABASE_LOCK; #undef connRequest
}
DWORD RoutingProtocolConnectionRequest(ULONG ProtocolId, ULONG InterfaceIndex) { PICB icbp; HANDLE hDIMInterface; DWORD rc;
ACQUIRE_DATABASE_LOCK;
if((icbp = GetInterfaceByIndex(InterfaceIndex)) == NULL) {
RELEASE_DATABASE_LOCK;
return ERROR_CAN_NOT_COMPLETE; }
if (icbp->ConnectionRequestPending) { RELEASE_DATABASE_LOCK;
return PENDING; }
// ask DDM to make a connection for this interface
hDIMInterface = icbp->hDIMInterface; icbp->ConnectionRequestPending = TRUE;
RELEASE_DATABASE_LOCK;
rc = (*ConnectInterface)(hDIMInterface, PID_IPX); ACQUIRE_DATABASE_LOCK;
if((icbp = GetInterfaceByIndex(InterfaceIndex)) == NULL) { RELEASE_DATABASE_LOCK;
return ERROR_CAN_NOT_COMPLETE; }
if (rc != PENDING) icbp->ConnectionRequestPending = FALSE; RELEASE_DATABASE_LOCK;
return rc; }
|