testexecmgmt/ucc/Source/hacontroller/CSHacontroller.cpp
changeset 0 3da2a79470a7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testexecmgmt/ucc/Source/hacontroller/CSHacontroller.cpp	Mon Mar 08 15:04:18 2010 +0800
@@ -0,0 +1,959 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:   
+* This file was autogenerated by rpcgen, but should be modified by the developer.
+* Make sure you don't use the -component_mod flag in future or this file will be overwritten.
+* Fri Oct 10 17:55:34 2003
+* Switches Includes
+* System Includes
+*
+*/
+
+
+
+
+#include <stdio.h>
+#include <signal.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#else
+#include <winsock2.h>
+#endif
+
+
+/****************************************************************************************
+ * 
+ * Local Includes
+ * 
+ ***************************************************************************************/
+#include "CSvcHacontroller.h"
+#include "CSHacontroller.h"
+#include "../IntegerAllocatorLibrary/CIntegerAllocator.h"
+
+
+/****************************************************************************************
+ * 
+ * Definition
+ * 
+ ***************************************************************************************/
+#define TEMPLATE_HA_CONFIG_FILE			"dynhad.template.conf"
+#define MOBILE_AGENT_COMMAND_LINE		"./dynhad --fg --debug --config "
+#define MAXCOMMANDLINELENGTH			(31 + 256 + 1)
+#define MAXTUNNELS                              32
+#define MAXINTERFACECONFIGENTRY			(IFNAMSIZ + 128)
+
+
+/****************************************************************************************
+ * 
+ * Macro Functions
+ * 
+ ***************************************************************************************/
+#ifdef WIN32
+#define API_SUCCESS                             (0)
+#define dynamics_ha_init(a)			(API_SUCCESS)
+#define dynamics_ha_get_status(a,b)		(API_SUCCESS)
+#define dynamics_ha_get_tunnels(a,b,c)		(API_SUCCESS)
+#define dynamics_ha_get_tunnel_info(a,b,c)	(API_SUCCESS)
+#define dynamics_ha_destroy_tunnel(a,b)		(API_SUCCESS)
+#define dynamics_ha_enable_mobile(a,b,c)	(API_SUCCESS)
+#define dynamics_ha_get_care_of_addr(a,b,c)	(API_SUCCESS)
+#endif
+
+ 
+/****************************************************************************************
+ * 
+ * Implementation
+ * 
+ ***************************************************************************************/
+CSHacontroller::CSHacontroller()
+{
+	iDynamicsCallTimeout = -1;
+	iAliasHostAddress = iAliasInterfaceIndex = 0;
+	iAgentProcess = NULL;
+}
+
+CSHacontroller::~CSHacontroller()
+{
+	assert( iAgentProcess == NULL );
+}
+
+int CSHacontroller::GetKey()
+{
+	return iKey;
+}
+
+void CSHacontroller::SetKey( int aKey )
+{
+	iKey = aKey;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: cstr_createagent
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::cstr_createagent( void )
+{
+	TResult rv;
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+
+	// create the virtual network
+	rv = CreateVirtualNetwork();
+	if( rv.iServiceResult != ERR_NONE ) {
+		return rv;
+	}
+
+	// create the interface alias
+	rv = CreateAliasInterface();
+	if( rv.iServiceResult != ERR_NONE ) {
+		RemoveVirtualNetwork();
+		return rv;
+	}
+
+	// create the dynamics config file
+	rv = CreateDynamicsConfigFile();
+	if( rv.iServiceResult != ERR_NONE ) {
+		RemoveVirtualNetwork();
+		RemoveAliasInterface();
+		return rv;
+	}
+
+	// done - success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: dstr_removeagent
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::dstr_removeagent( int aArgs, int *aDeleteInstance )
+{
+	TResult rv, rv_config, rv_interface, rv_vn;
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+
+	// make sure that the proces isn't running
+	if( iAgentProcess != NULL ) {
+	  *aDeleteInstance = 0;
+	  rv.iServiceResult = ERR_INVALIDSTATE;
+	  return rv;
+	}
+
+	// cleanup the virtual network
+	rv_vn = RemoveVirtualNetwork();
+
+	// cleanup the dynamics config file
+	rv_config = RemoveDynamicsConfigFile();
+	
+	// cleanup the alias interface 
+	rv_interface = RemoveAliasInterface();
+
+	// check for errors
+	if( rv_vn.iServiceResult != ERR_NONE ) {
+		return rv_vn;
+	}
+	if( rv_config.iServiceResult != ERR_NONE ) {
+		return rv_config;
+	}
+	if( rv_interface.iServiceResult != ERR_NONE ) {
+		return rv_interface;
+	}
+
+	// done - success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: startmobileagent
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::startmobileagent( int aArgs )
+{
+	TResult rv;
+	int errcode;
+	TCAProcessError perr;
+	char command_line_str[MAXCOMMANDLINELENGTH];
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+
+	// check that there is currently no process
+	if( iAgentProcess != NULL ) {
+		rv.iServiceResult = ERR_INVALIDSTATE;
+		rv.iSubComponentResult = 0;
+		rv.iData0 = 0;
+		return rv;
+	}
+
+	// create the new process object
+	iAgentProcess = new CAProcess();
+	assert( iAgentProcess != NULL );
+
+	// construct the command line
+	snprintf( command_line_str, MAXCOMMANDLINELENGTH, "%s%s", MOBILE_AGENT_COMMAND_LINE, iDynamicsConfigFile.GetLocalFilename() );
+
+	// start the actual process
+	perr = iAgentProcess->StartProcess( command_line_str, &errcode, false, false, false ); 
+	if( perr != CAE_NONE ) {
+		rv.iServiceResult = ERR_START_PROCESS_ERROR;
+		rv.iSubComponentResult = (int)perr;
+		rv.iData0 = errcode;
+		delete iAgentProcess;
+		iAgentProcess = NULL;
+		return rv;
+	}
+
+	// done - success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: stopmobileagent
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::stopmobileagent( int aArgs )
+{
+	TResult rv;
+	TCAProcessError perr;
+	TProcessStatus pstatus;
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+	
+	// if the process isn't started then invalid state
+	if( iAgentProcess == NULL ) {
+	  rv.iServiceResult = ERR_INVALIDSTATE;
+	  return rv;
+	}
+
+	// if the process isn't running then it has died outside the scope of this controller, clean up the state, return an error since
+	// this is noteworthy and should be either expected or not happen.
+	perr = iAgentProcess->GetProcessStatus( &pstatus );
+	assert( perr == CAE_NONE );
+	if( pstatus != PS_STARTED ) {
+	  assert( (pstatus == PS_STOPPED) || (pstatus == PS_ABANDONNED) );
+	  delete iAgentProcess;
+	  iAgentProcess = NULL;
+	  rv.iServiceResult = ERR_PROCESS_TERMINATED_OUTSIDE_SCOPE;
+	  return rv;
+	}
+
+	// request the process to stop
+	perr = iAgentProcess->RequestStop( SIGTERM );
+	if( perr != CAE_NONE ) {
+	  rv.iServiceResult = ERR_STOP_PROCESS_ERROR;
+	  rv.iSubComponentResult = (int)perr;
+	  return rv;
+	}
+
+	// wait for the process to stop
+	perr = iAgentProcess->WaitForProcessToTerminate( -1 );
+	if( perr != CAE_NONE ) {
+	  rv.iServiceResult = ERR_WAIT_PROCESS_ERROR;
+	  rv.iSubComponentResult = (int)perr;
+	  return rv;
+	}
+
+	// remove the process
+	delete iAgentProcess;
+	iAgentProcess = NULL;
+
+	// done - success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: getmobileagentstatus
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::getmobileagentstatus( int aArgs )
+{
+	TResult rv;
+	TCAProcessError perr;
+	TProcessStatus pstatus;
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+
+	// if the process doesn't exist then we return PS_INVALID
+	if( iAgentProcess == NULL ) {
+		rv.iData0 = PS_INVALID;
+		return rv;
+	}
+
+	// otherwise just return whatever iAgentProcess->GetProcessStatus() returns
+	perr = iAgentProcess->GetProcessStatus( &pstatus );
+	assert( perr == CAE_NONE );
+	rv.iData0 = (int)pstatus;
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: setsingleoption
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::setsingleoption( TOptionDesc aArgs )
+{
+	TResult rv;
+	int errcode;
+	TDCFError cerr;
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+
+	// make sure that the process isn't running
+	if( iAgentProcess != NULL ) {
+		rv.iServiceResult = ERR_INVALIDSTATE;
+		return rv;
+	}
+
+	// modify the config file
+	cerr = iDynamicsConfigFile.SetSingleOption( aArgs.iOptionToken, aArgs.iOptionValue, &errcode );
+	if( cerr != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)cerr;
+		rv.iData0 = errcode;
+		return rv;
+	}
+
+	// return success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: removesingleoption
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::removesingleoption( TOptionDesc aArgs )
+{
+	TResult rv;
+	int errcode;
+	TDCFError cerr;
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+
+	// make sure that the process isn't running
+	if( iAgentProcess != NULL ) {
+		rv.iServiceResult = ERR_INVALIDSTATE;
+		return rv;
+	}
+
+	// modify the config file
+	cerr = iDynamicsConfigFile.RemoveSingleOption( aArgs.iOptionToken, &errcode );
+	if( cerr != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)cerr;
+		rv.iData0 = errcode;
+		return rv;
+	}
+
+	// return success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: addlistoption
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::addlistoption( TOptionDesc aArgs )
+{
+	TResult rv;
+	int errcode;
+	TDCFError cerr;
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+
+	// make sure that the process isn't running
+	if( iAgentProcess != NULL ) {
+		rv.iServiceResult = ERR_INVALIDSTATE;
+		return rv;
+	}
+
+	// modify the config file
+	cerr = iDynamicsConfigFile.AddListOption( aArgs.iOptionBlockStart, aArgs.iOptionBlockEnd, aArgs.iOptionValue, &errcode );
+	if( cerr != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)cerr;
+		rv.iData0 = errcode;
+		return rv;
+	}
+
+	// return success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: removelistoption
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::removelistoption( TOptionDesc aArgs )
+{
+	TResult rv;
+	int errcode;
+	TDCFError cerr;
+
+	// initialise the result
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	rv.iData1 = 0;
+
+	// make sure that the process isn't running
+	if( iAgentProcess != NULL ) {
+		rv.iServiceResult = ERR_INVALIDSTATE;
+		rv.iSubComponentResult = 0;
+		rv.iData0 = 0;
+		return rv;
+	}
+
+	// modify the config file
+	cerr = iDynamicsConfigFile.RemoveListOption( aArgs.iOptionBlockStart, aArgs.iOptionBlockEnd, aArgs.iOptionToken, &errcode );
+	if( cerr != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)cerr;
+		rv.iData0 = errcode;
+		return rv;
+	}
+
+	// return success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: getstatus
+ * 
+ ***************************************************************************************/
+THaStatus CSHacontroller::getstatus( int aArgs )
+{
+	TResult res;
+	THaStatus rv;
+	TDynamicsCallInfo cres;
+	THomeAgentStatusInfo home_agent_info;
+
+	// init the return value
+	memset( &rv, 0, sizeof(rv) );
+	rv.iCallResult.iServiceResult = ERR_NONE;
+	
+	// add the info about the virtual network
+	rv.iHomeAgentAddress = inet_addr( iAliasInterfaceAddress.c_str() );
+	rv.iVirtualNetworkStartAddress = iVirtualNetworkSegmentAddress;
+	rv.iVirtualNetworkSize = iVirtualNetworkSegmentSize;
+
+	// if the agent is not running then we are done
+	res = is_agent_running();
+	if( res.iServiceResult != ERR_NONE ) {
+		return rv;
+	}
+
+	// make the call to dynamics
+	cres = iDynamicsCommand.HomeAgentGetStatus( &home_agent_info );
+	if( cres.iResult != DC_SUCCESS ) {
+		set_dynamics_error( &(rv.iCallResult), &cres );
+		return rv;
+	}
+
+	// set the result
+	rv.iAdvertisementsSent = home_agent_info.iAdvertisementsSent;
+	rv.iDiscardedMalformed = home_agent_info.iDiscardedMalformed;
+	rv.iDiscardedUnknownExtension = home_agent_info.iDiscardedUnknownExtension;
+	rv.iDiscardedVendor = home_agent_info.iDiscardedVendor;
+	rv.iRequestsAccepted = home_agent_info.iRequestsAccepted;
+	rv.iRequestsRejected = home_agent_info.iRequestsRejected;
+	rv.iTunnelCount = home_agent_info.iTunnelCount;
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: destroytunnelid
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::destroytunnelid( THaTunnelID aArgs )
+{
+	TResult rv;
+	TDynamicsCallInfo cres;
+
+	// init the return value
+	memset( &rv, 0, sizeof(rv) );
+	rv.iServiceResult = ERR_NONE;
+	
+	// check that the agent is running
+	rv = is_agent_running();
+	if( rv.iServiceResult != ERR_NONE ) {
+		return rv;
+	}
+
+	// make the call to dynamics
+	cres = iDynamicsCommand.HomeAgentDestroyTunnel( aArgs.iMobileNodeAddress );
+	if( cres.iResult != DC_SUCCESS ) {
+		set_dynamics_error( &rv, &cres );
+		return rv;
+	}
+
+	// done 
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: listtunnels
+ * 
+ ***************************************************************************************/
+THaTunnelList CSHacontroller::listtunnels( int aArgs )
+{
+	TResult res;
+	THaTunnelList rv = { 0, NULL };
+	TDynamicsCallInfo cres;
+	unsigned int tunnel_list[MAXTUNNELS];
+	int tunnel_count = MAXTUNNELS, i;
+
+	// check that the agent is running
+	res = is_agent_running();
+	if( res.iServiceResult != ERR_NONE ) {
+		return rv;
+	}
+
+	// make the call to dynamics
+	cres = iDynamicsCommand.HomeAgentGetTunnels( &tunnel_count, tunnel_list );
+	if( cres.iResult != DC_SUCCESS ) {
+		return rv;
+	}
+
+	// allocate memory for the list
+	rv.THaTunnelList_len = tunnel_count;
+	rv.THaTunnelList_val = (THaTunnelID*)calloc( tunnel_count, sizeof(THaTunnelID) );
+	assert( rv.THaTunnelList_val != NULL );
+
+	// now return the information
+	for( i = 0; i < tunnel_count; i++ ) {
+		(rv.THaTunnelList_val)[i].iAgentID = 0;
+		(rv.THaTunnelList_val)[i].iMobileNodeAddress = tunnel_list[i];
+	}
+
+	// done - success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: gettunnelinfo
+ * 
+ ***************************************************************************************/
+THaTunnelInfo CSHacontroller::gettunnelinfo( TGetTunnelRequest aArgs )
+{
+	THaTunnelInfo rv;
+	TDynamicsCallInfo cres;
+	THomeAgentTunnelInfo hati;
+
+	// init the result
+	memset( &rv, 0, sizeof(rv) );
+	rv.iCallResult.iServiceResult = ERR_NONE;
+
+	// check that the agent is running
+	rv.iCallResult = is_agent_running();
+	if( rv.iCallResult.iServiceResult != ERR_NONE ) {
+		return rv;
+	}
+
+	// make the call to dynamics
+	cres = iDynamicsCommand.HomeAgentGetTunnelInfo( aArgs.iMobileNodeAddress, &hati );
+	if( cres.iResult != DC_SUCCESS ) {
+		set_dynamics_error( &(rv.iCallResult), &cres );
+		return rv;
+	}
+
+	// set the info
+	rv.iCareofAddress = hati.iCareofAddress;
+	rv.iCreationTime = hati.iCreationTime;
+	rv.iExpirationTime = hati.iExpirationTime;
+	rv.iHomeAgentAddress = hati.iHomeAgentAddress;
+	rv.iLastTimestamp = hati.iLastTimestamp;
+	rv.iMobileNodeAddress = hati.iMobileNodeAddress;
+	rv.iRefreshTime = hati.iRefreshTime;
+	rv.iSPI = hati.iSPI;
+	rv.iTimeout = hati.iTimeout;
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PUBLIC FUNCTION: settimeout
+ * 
+ ***************************************************************************************/
+void CSHacontroller::settimeout( TTimeoutRequest aArgs )
+{
+	iDynamicsCallTimeout = aArgs.iTimeout;
+}
+
+
+/****************************************************************************************
+ * 
+ * PRIVATE FUNCTION: CreateDynamicsConfigFile
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::CreateDynamicsConfigFile()
+{
+	TResult rv;
+	int errcode;
+	TDCFError config_file_error;
+	char dynamics_config[MAXINTERFACECONFIGENTRY];
+	struct in_addr iaddr;
+	TStartupInfo startupinfo;
+
+	// initialise the rv - always be optimistic!
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+
+	// set the reference file
+	config_file_error = iDynamicsConfigFile.SetReferenceFile( TEMPLATE_HA_CONFIG_FILE );
+	if( config_file_error != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)config_file_error;
+		return rv;
+	}
+
+	// create a local copy
+	config_file_error = iDynamicsConfigFile.CreateLocalCopy( &errcode );
+	if( config_file_error != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)config_file_error;
+		rv.iData0 = errcode;
+		return rv;
+	}
+
+	// get the startup info
+	startupinfo = CSvcHacontroller::GetStartupInfo();
+
+	// add the listen interface
+	snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "eth%d:%d 0 1 30", startupinfo.iBaseInterfaceIndex, iAliasInterfaceIndex );
+	config_file_error = iDynamicsConfigFile.AddListOption( "INTERFACES_BEGIN", "INTERFACES_END", dynamics_config, &errcode );
+	if( config_file_error != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)config_file_error;
+		rv.iData0 = errcode;
+		iDynamicsConfigFile.RemoveLocalCopy( &errcode );
+		return rv;
+	}
+
+	// add the home network addresses to the authorized list
+	iaddr.ADDRESS_INTEGER = iVirtualNetworkSegmentAddress;
+	snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "1000 %s/%d", inet_ntoa(iaddr), iVirtualNetworkSegmentNetmaskBitcount );
+	config_file_error = iDynamicsConfigFile.AddListOption( "AUTHORIZEDLIST_BEGIN", "AUTHORIZEDLIST_END", dynamics_config, &errcode );
+	if( config_file_error != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)config_file_error;
+		rv.iData0 = errcode;
+		iDynamicsConfigFile.RemoveLocalCopy( &errcode );
+		return rv;
+	}
+	
+	// done
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PRIVATE FUNCTION: RemoveDynamicsConfigFile
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::RemoveDynamicsConfigFile()
+{
+	TResult rv;
+	TDCFError terr;
+	int errcode;
+
+	// initialise the rv - always be optimistic!
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+
+	// clean up the config file
+	terr = iDynamicsConfigFile.RemoveLocalCopy( &errcode );
+	if( terr != DCE_NONE ) {
+		rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
+		rv.iSubComponentResult = (int)terr;
+		rv.iData0 = errcode;
+		return rv;
+	}
+
+	// done
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PRIVATE FUNCTION: CreateAliasInterface
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::CreateAliasInterface()
+{
+	TResult rv;
+	int errcode;
+	CIntegerAllocator *alias_host_address_allocator;
+	TStartupInfo startup_info;
+	TInterfaceAliasError interface_alias_error;
+
+	// initialise the rv - always be optimistic!
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+
+	// get the host address allocator
+	alias_host_address_allocator = CSvcHacontroller::GetAliasHostAddressAllocator();
+
+	// get a host address
+	assert( alias_host_address_allocator != NULL );
+	iAliasHostAddress = alias_host_address_allocator->AllocateInteger();
+	if( iAliasHostAddress == -1 ) {
+		rv.iServiceResult = ERR_NO_MORE_INTERFACES;
+		return rv;
+	}
+//	fprintf( stderr, "DEBUG: iAliasHostAddress = %d\n", iAliasHostAddress );
+
+	// get the startup info
+	startup_info = CSvcHacontroller::GetStartupInfo();
+
+	// create an alias
+	interface_alias_error = iAgentInterface.CreateNewInterfaceAlias( startup_info.iBaseInterfaceIndex, 
+									 startup_info.iBaseInterfaceNetworkMask, 
+									 iAliasHostAddress, &iAliasInterfaceIndex, &errcode );
+	if( interface_alias_error != IE_NONE ) {
+	  rv.iServiceResult = ERR_CREATE_INTERFACE_ERROR;
+	  rv.iSubComponentResult = (int)interface_alias_error;
+	  rv.iData0 = errcode;
+	  alias_host_address_allocator->FreeInteger( iAliasHostAddress );
+	  return rv;
+	}
+
+	// get the complete interface address as a string
+	interface_alias_error = iAgentInterface.GetInterfaceAddress( &iAliasInterfaceAddress );
+	assert( interface_alias_error == IE_NONE );
+
+	// done success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PRIVATE FUNCTION: RemoveAliasInterface
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::RemoveAliasInterface()
+{
+	int err, errcode;
+	TResult rv;
+	TInterfaceAliasError interface_alias_error;
+	CIntegerAllocator *alias_host_address_allocator;
+
+	// initialise the rv - always be optimistic!
+	rv.iServiceResult = ERR_NONE;
+	rv.iSubComponentResult = 0;
+	rv.iData0 = 0;
+	
+	// destroy the interface alias
+	interface_alias_error = iAgentInterface.DestroyInterfaceAlias( &errcode );
+	if( interface_alias_error != IE_NONE ) {
+		rv.iServiceResult = ERR_DESTROY_INTERFACE_ERROR;
+		rv.iSubComponentResult = (int)interface_alias_error;
+		rv.iData0 = errcode;
+		return rv;
+	}
+
+	// get the host address allocator
+	alias_host_address_allocator = CSvcHacontroller::GetAliasHostAddressAllocator();
+
+	// free the host address
+	err = alias_host_address_allocator->FreeInteger( iAliasHostAddress );
+	assert( err == 0 );
+
+	// done
+	iAliasHostAddress = iAliasInterfaceIndex = 0;
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PRIVATE FUNCTION: CreateVirtualNetwork
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::CreateVirtualNetwork()
+{
+	TResult rv;
+	int segment_size, err, segment_netmask_bitcount;
+	CNetworkPartitionManager *virtual_network_partition_allocator;
+
+	// init the rv
+	memset( &rv, 0, sizeof(rv) );
+	rv.iServiceResult = ERR_NONE;
+
+	// get the virtual network partition allocator
+	virtual_network_partition_allocator = CSvcHacontroller::GetNetworkPartitionManager();
+	assert( virtual_network_partition_allocator != NULL );
+
+	// get a virtual network partition to use
+	err = virtual_network_partition_allocator->AllocateNetworkSegment( &segment_netmask_bitcount, &segment_size );
+	if( err == -1 ) {
+		rv.iServiceResult = ERR_NO_MORE_VIRTUAL_NETWORKS;
+		return rv;
+	}
+
+	// save this information 
+	iVirtualNetworkSegmentAddress = err;
+	iVirtualNetworkSegmentSize = segment_size;
+	iVirtualNetworkSegmentNetmaskBitcount = segment_netmask_bitcount;
+
+	// done - ok
+	rv.iServiceResult = ERR_NONE;
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PRIVATE FUNCTION: RemoveVirtualNetwork
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::RemoveVirtualNetwork()
+{
+	int err;
+	TResult rv;
+	CNetworkPartitionManager *virtual_network_partition_allocator;
+
+	// init the rv
+	memset( &rv, 0, sizeof(rv) );
+	rv.iServiceResult = ERR_NONE;
+
+	// get the virtual network partition allocator
+	virtual_network_partition_allocator = CSvcHacontroller::GetNetworkPartitionManager();
+	assert( virtual_network_partition_allocator != NULL );
+
+	// free the network address
+	err = virtual_network_partition_allocator->FreeNetworkSegment( iVirtualNetworkSegmentAddress );
+	assert( err == 0 );
+
+	// clear-up the state
+	iVirtualNetworkSegmentAddress = iVirtualNetworkSegmentSize = 0;
+
+	// done 
+	rv.iServiceResult = ERR_NONE;
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PRIVATE FUNCTION: is_agent_running
+ * 
+ ***************************************************************************************/
+TResult CSHacontroller::is_agent_running()
+{	
+	TResult rv;
+	TCAProcessError perr;
+	TProcessStatus pstatus;
+
+	// init the rv
+	memset( &rv, 0, sizeof(rv) );
+	rv.iServiceResult = ERR_NONE;
+
+	// check that the agent was running
+	if( iAgentProcess == NULL ) {
+		rv.iServiceResult = ERR_INVALIDSTATE;
+		return rv;
+	}
+
+	// check that the agent is still runnning
+	perr = iAgentProcess->GetProcessStatus( &pstatus );
+	assert( perr == CAE_NONE );
+	if( pstatus != PS_STARTED ) {
+		rv.iServiceResult = ERR_INVALIDSTATE;
+		return rv;
+	}
+
+	// done - success
+	return rv;
+}
+
+
+/****************************************************************************************
+ * 
+ * PRIVATE FUNCTION: is_agent_running
+ * 
+ ***************************************************************************************/
+void CSHacontroller::set_dynamics_error( TResult *result, TDynamicsCallInfo *cres )
+{
+	result->iServiceResult = ERR_DYNAMICS_CALL_FAILED;
+	result->iSubComponentResult = cres->iResult;
+	result->iData0 = cres->iErrorCode;
+	result->iData1 = cres->iErrorDetail;
+}