/*++ 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; }