|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
update.c
Abstract:
The auto-static update routines
Author:
Stefan Solomon 05/18/1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
VOID SaveUpdate(PVOID InterfaceIndex);
VOID RestoreInterface (PVOID InterfaceIndex);
/*++
Function: RequestUpdate
Descr: Called to initiate an auto static update of routes and services on the specified interface.
--*/
DWORD RequestUpdate(IN HANDLE InterfaceIndex, IN HANDLE hEvent) { PICB icbp; DWORD rc; BOOL RoutesUpdateStarted = FALSE; BOOL ServicesUpdateStarted = FALSE;
Trace(UPDATE_TRACE, "RequestUpdate: Entered for if # %d\n", InterfaceIndex);
ACQUIRE_DATABASE_LOCK;
if(RouterOperState != OPER_STATE_UP) {
RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
RELEASE_DATABASE_LOCK;
Trace(UPDATE_TRACE, "RequestUpdate: Nonexistent interface with # %d\n", InterfaceIndex);
return ERROR_INVALID_HANDLE; }
SS_ASSERT(!memcmp(&icbp->Signature, InterfaceSignature, 4));
// check if the interface is bound to a connected adapter
if(icbp->OperState != OPER_STATE_UP) {
RELEASE_DATABASE_LOCK;
Trace(UPDATE_TRACE, "RequestUpdate: adapter not connected on if # %d\n", InterfaceIndex);
return ERROR_NOT_CONNECTED; }
// check if an update is already pending
if(IsUpdateRequestPending(icbp)) {
RELEASE_DATABASE_LOCK;
Trace(UPDATE_TRACE, "RequestUpdate: update already pending on if # %d\n", InterfaceIndex);
return ERROR_UPDATE_IN_PROGRESS; }
//
// *** Start a new update ***
//
icbp->DIMUpdateEvent = hEvent;
if((rc = RtProtRequestRoutesUpdate(icbp->InterfaceIndex)) == NO_ERROR) {
icbp->UpdateReq.RoutesReqStatus = UPDATE_PENDING; } else {
Trace(UPDATE_TRACE, "RequestUpdate: Routing Update is Disabled\n"); }
if((rc = RtProtRequestServicesUpdate(icbp->InterfaceIndex)) == NO_ERROR) {
icbp->UpdateReq.ServicesReqStatus = UPDATE_PENDING; } else { Trace(UPDATE_TRACE, "RequestUpdate: Services Update is Disabled\n"); }
// if at least one of the protocols initiated the update, we qualify
// the request as successfull, else it failed.
if(!IsUpdateRequestPending(icbp)) {
RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
RELEASE_DATABASE_LOCK; return PENDING; }
/*++
Function: UpdateCompleted
Descr: Invoked by the router manager worker when the routing protocol signals completion of the update request
--*/
VOID UpdateCompleted(PUPDATE_COMPLETE_MESSAGE ucmsgp) { PICB icbp; BOOL UpdateDone; ULONG InterfaceIndex; HANDLE hDIMInterface; #if DBG
char *updttype;
#endif
Trace(UPDATE_TRACE, "UpdateCompleted: Entered\n");
UpdateDone = FALSE;
ACQUIRE_DATABASE_LOCK;
if((icbp = GetInterfaceByIndex(ucmsgp->InterfaceIndex)) == NULL) {
RELEASE_DATABASE_LOCK;
Trace(UPDATE_TRACE, "UpdateCompleted: Nonexistent interface with # %d\n", ucmsgp->InterfaceIndex);
return; }
InterfaceIndex = icbp->InterfaceIndex;
// check if we have requested one, if not just discard
if(!IsUpdateRequestPending(icbp)) {
RELEASE_DATABASE_LOCK; return; }
// fill in the result and check if we're done
if(ucmsgp->UpdateType == DEMAND_UPDATE_ROUTES) {
// ROUTES UPDATE
Trace(UPDATE_TRACE, "UpdateCompleted: Routes update req done for if # %d with status %d\n", ucmsgp->InterfaceIndex, ucmsgp->UpdateStatus);
if(ucmsgp->UpdateStatus == NO_ERROR) {
icbp->UpdateReq.RoutesReqStatus = UPDATE_SUCCESSFULL;
// if the update was successfull we delete all the static routes
// for this interface, and then CONVERT all the routes added by the
// protocol which did the update on this interface to static routes.
DeleteAllStaticRoutes(icbp->InterfaceIndex);
ConvertAllProtocolRoutesToStatic(icbp->InterfaceIndex, UpdateRoutesProtId); } else { icbp->UpdateReq.RoutesReqStatus = UPDATE_FAILURE; }
if(icbp->UpdateReq.ServicesReqStatus != UPDATE_PENDING) {
// we are done
UpdateDone = TRUE; } } else { // SERVICES UPDATE
Trace(UPDATE_TRACE, "UpdateCompleted: Services update req done for if # %d with status %d\n", ucmsgp->InterfaceIndex, ucmsgp->UpdateStatus);
if(ucmsgp->UpdateStatus == NO_ERROR) {
icbp->UpdateReq.ServicesReqStatus = UPDATE_SUCCESSFULL;
// we delete all the static services for this interface and then
// CONVERT all the services added by the protocol which did the
// update routes on this interface to static services
DeleteAllStaticServices(InterfaceIndex);
ConvertAllServicesToStatic(InterfaceIndex); } else { icbp->UpdateReq.ServicesReqStatus = UPDATE_FAILURE; }
if(icbp->UpdateReq.RoutesReqStatus != UPDATE_PENDING) {
// we are done
UpdateDone = TRUE; } }
if(UpdateDone) {
if((icbp->UpdateReq.RoutesReqStatus == UPDATE_SUCCESSFULL) && (icbp->UpdateReq.ServicesReqStatus == UPDATE_SUCCESSFULL)) {
icbp->UpdateResult = NO_ERROR; } else { if((icbp->UpdateReq.RoutesReqStatus == UPDATE_FAILURE) || (icbp->UpdateReq.ServicesReqStatus == UPDATE_FAILURE)) {
icbp->UpdateResult = ERROR_CAN_NOT_COMPLETE; } else { // this is for the case when one or both protocols couldn't
// do updates because they were not configured to update.
icbp->UpdateResult = NO_ERROR; } }
ResetUpdateRequest(icbp);
if(icbp->MIBInterfaceType != IF_TYPE_ROUTER_WORKSTATION_DIALOUT) {
SetEvent(icbp->DIMUpdateEvent); CloseHandle (icbp->DIMUpdateEvent); icbp->DIMUpdateEvent = NULL; } }
// complete the update action by signaling DIM the final result
// and saving the update result on disk
if(UpdateDone && (icbp->MIBInterfaceType != IF_TYPE_ROUTER_WORKSTATION_DIALOUT)) {
InterfaceIndex = icbp->InterfaceIndex;
if(RtlQueueWorkItem((icbp->UpdateResult == NO_ERROR) ? SaveUpdate : RestoreInterface, (PVOID)UlongToPtr(InterfaceIndex), 0) == STATUS_SUCCESS) {
WorkItemsPendingCounter++; } }
RELEASE_DATABASE_LOCK; }
/*++
Function: SaveUpdate
Descr: Saves the new interface configuration on permanent storage
--*/
VOID SaveUpdate(PVOID InterfaceIndex) { LPVOID InterfaceInfop = NULL; ULONG InterfaceInfoSize = 0; DWORD rc; HANDLE hDIMInterface; PICB icbp;
if(RouterOperState != OPER_STATE_UP) {
goto Exit; }
rc = GetInterfaceInfo((HANDLE)InterfaceIndex, InterfaceInfop, &InterfaceInfoSize);
if(rc != ERROR_INSUFFICIENT_BUFFER) {
// !!! log an error !!!
goto Exit; }
InterfaceInfop = GlobalAlloc(GPTR, InterfaceInfoSize);
if(InterfaceInfop == NULL) {
// !!! log error !!!
goto Exit; }
rc = GetInterfaceInfo((HANDLE)InterfaceIndex, InterfaceInfop, &InterfaceInfoSize);
if(rc != NO_ERROR) {
// !!! log error !!!
GlobalFree(InterfaceInfop);
goto Exit; }
ACQUIRE_DATABASE_LOCK;
if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
RELEASE_DATABASE_LOCK; goto Exit; }
hDIMInterface = icbp->hDIMInterface;
RELEASE_DATABASE_LOCK;
// save the info on disk
rc = SaveInterfaceInfo(hDIMInterface, PID_IPX, InterfaceInfop, InterfaceInfoSize);
SS_ASSERT(rc == NO_ERROR);
GlobalFree(InterfaceInfop);
Exit:
ACQUIRE_DATABASE_LOCK;
WorkItemsPendingCounter--;
RELEASE_DATABASE_LOCK; }
/*++
Function: RestoreInterface
Descr: Restore interface configuration from permanent storage
--*/
VOID RestoreInterface (PVOID InterfaceIndex) { LPVOID InterfaceInfop = NULL; ULONG InterfaceInfoSize = 0; DWORD rc; HANDLE hDIMInterface; PICB icbp;
if(RouterOperState != OPER_STATE_UP) {
goto Exit; }
ACQUIRE_DATABASE_LOCK;
if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
RELEASE_DATABASE_LOCK; goto Exit; }
hDIMInterface = icbp->hDIMInterface;
RELEASE_DATABASE_LOCK;
// get the info from disk
InterfaceInfoSize = 0; InterfaceInfop = NULL; rc = RestoreInterfaceInfo (hDIMInterface, PID_IPX, InterfaceInfop, &InterfaceInfoSize); if (rc==ERROR_BUFFER_TOO_SMALL) { InterfaceInfop = GlobalAlloc (GMEM_FIXED, InterfaceInfoSize); if (InterfaceInfop!=NULL) { rc = RestoreInterfaceInfo(hDIMInterface, PID_IPX, InterfaceInfop, &InterfaceInfoSize); } else rc = GetLastError (); }
if (rc == NO_ERROR) rc = SetInterfaceInfo (InterfaceIndex, InterfaceInfop);
if (InterfaceInfop!=NULL) GlobalFree(InterfaceInfop);
Exit:
ACQUIRE_DATABASE_LOCK;
WorkItemsPendingCounter--;
RELEASE_DATABASE_LOCK; }
/*++
Function: GetDIMUpdateResult
Descr: Called by DDM to retrieve a message posted for it
--*/
DWORD GetDIMUpdateResult(IN HANDLE InterfaceIndex, OUT LPDWORD UpdateResultp) { PLIST_ENTRY lep; PICB icbp;
ACQUIRE_DATABASE_LOCK;
if(RouterOperState != OPER_STATE_UP) {
RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
if((icbp = GetInterfaceByIndex(PtrToUlong(InterfaceIndex))) == NULL) {
RELEASE_DATABASE_LOCK; return ERROR_INVALID_PARAMETER; }
// check that the update is not pending
if(IsUpdateRequestPending(icbp)) {
RELEASE_DATABASE_LOCK; return ERROR_CAN_NOT_COMPLETE; }
*UpdateResultp = icbp->UpdateResult;
RELEASE_DATABASE_LOCK;
return NO_ERROR; }
|