/*
* 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.
* Mon Oct 06 12:02:04 2003
* System Includes
*
*/
#include <stdio.h>
#include <signal.h>
#ifndef WIN32
#include <unistd.h>
#include <net/if.h>
#endif
/****************************************************************************************
*
* Local Includes
*
***************************************************************************************/
#include "CSvcFacontroller.h"
#include "CSFacontroller.h"
/****************************************************************************************
*
* Definition
*
***************************************************************************************/
#define TEMPLATE_CONFIG_FILE "dynfad.template.conf"
#define MOBILE_AGENT_COMMAND_LINE "./dynfad --fg --debug --config "
#define MAXCOMMANDLINELENGTH (31 + 256 + 1)
#define MAXTUNNELS 32
#define MAXINTERFACECONFIGENTRY (IFNAMSIZ + 128)
#define CONFIGCOUNT 16
/*******************************************************************************
*
* Macro Functions
*
******************************************************************************/
/****************************************************************************************
*
* Implementation
*
***************************************************************************************/
CSFacontroller::CSFacontroller()
{
iDynamicsCallTimeout = -1;
iAgentProcess = NULL;
}
CSFacontroller::~CSFacontroller()
{
assert( iAgentProcess == NULL );
}
int CSFacontroller::GetKey()
{
return iKey;
}
void CSFacontroller::SetKey( int aKey )
{
iKey = aKey;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: cstr_createagent
*
***************************************************************************************/
TResult CSFacontroller::cstr_createagent( void )
{
TResult rv;
TDCFError terr, terr_a[CONFIGCOUNT];
TInterfaceAliasError ierr;
TStartupInfo startup_info;
CIntegerAllocator *ialloc;
char dynamics_config[MAXINTERFACECONFIGENTRY];
string interface_name, interface_address;
int errcode, i;
// initialise the result
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// get an address for the new interface alias
ialloc = CSvcFacontroller::GetIntegerAllocator();
assert( ialloc != NULL );
iInterfaceHostAddress = ialloc->AllocateInteger();
if( iInterfaceHostAddress == -1 ) {
rv.iServiceResult = ERR_NO_MORE_INTERFACES;
return rv;
}
// create a local copy of the configuration file
terr = iDynamicsConfigFile.SetReferenceFile( TEMPLATE_CONFIG_FILE );
if( terr != DCE_NONE ) {
ialloc->FreeInteger( iInterfaceHostAddress );
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
return rv;
}
terr = iDynamicsConfigFile.CreateLocalCopy( &errcode );
if( terr != DCE_NONE ) {
ialloc->FreeInteger( iInterfaceHostAddress );
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
rv.iData0 = errcode;
return rv;
}
// create an alias interface to use
startup_info = CSvcFacontroller::GetStartupInfo();
ierr = iAgentInterface.CreateNewInterfaceAlias( startup_info.iBaseInterfaceIndex, startup_info.iNetworkMask, iInterfaceHostAddress, &iInterfaceIndex, &errcode );
if( ierr != IE_NONE ) {
rv.iServiceResult = ERR_CREATE_INTERFACE_ERROR;
rv.iSubComponentResult = ierr;
rv.iData0 = errcode;
ialloc->FreeInteger( iInterfaceHostAddress );
iDynamicsConfigFile.RemoveLocalCopy( &errcode );
return rv;
}
ierr = iAgentInterface.GetInterfaceAddress( &interface_address );
assert( ierr == IE_NONE );
// set the interface name in the config file
ierr = iAgentInterface.GetInterfaceName( &interface_name );
snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "%s 2 -1 10", interface_name.c_str() );
terr_a[0] = iDynamicsConfigFile.AddListOption( "INTERFACES_BEGIN", "INTERFACES_END", dynamics_config, &errcode );
// set the tunnel name prefix to a unique value for this agent
// snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "TunnelDevice \"TUNL-%s-\"", interface_name.c_str() );
snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "TunnelDevice \"TUNL\"" );
terr_a[1] = iDynamicsConfigFile.SetSingleOption( "TunnelDevice", dynamics_config, &errcode );
// set the FA addresses to the alias interface address
snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "HighestFAIPAddress %s", interface_address.c_str() );
terr_a[2] = iDynamicsConfigFile.SetSingleOption( "HighestFAIPAddress", dynamics_config, &errcode );
// set the FA addresses to the alias interface address
snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "UpperFAIPAddress %s", interface_address.c_str() );
terr_a[3] = iDynamicsConfigFile.SetSingleOption( "UpperFAIPAddress", dynamics_config, &errcode );
// see if any errors occured setting the config info
for( i = 0; i < 3; i++ ) {
if( terr_a[i] != DCE_NONE ) {
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr_a[i];
iAgentInterface.DestroyInterfaceAlias( &errcode );
ialloc->FreeInteger( iInterfaceHostAddress );
iDynamicsConfigFile.RemoveLocalCopy( &errcode );
return rv;
}
}
// done - success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: dstr_removeagent
*
***************************************************************************************/
int CSFacontroller::dstr_removeagent( int aArgs, int *aDeleteInstance )
{
int rv = ERR_NONE, errcode;
TDCFError terr;
TInterfaceAliasError ierr;
CIntegerAllocator *ialloc;
// make sure that the proces isn't running
if( iAgentProcess != NULL ) {
*aDeleteInstance = 0;
rv = ERR_INVALIDSTATE;
return rv;
}
// free the interface index
ialloc = CSvcFacontroller::GetIntegerAllocator();
assert( ialloc != NULL );
ialloc->FreeInteger( iInterfaceHostAddress );
// clean up the config file
terr = iDynamicsConfigFile.RemoveLocalCopy( &errcode );
// destroy the interface alias
ierr = iAgentInterface.DestroyInterfaceAlias( &errcode );
// check for errors from the config file - delete the instance in any case
if( terr != DCE_NONE ) {
rv = ERR_CONFIG_FILE_ERROR;
return rv;
}
// check for errors from the interface alias - delete the instance
if( ierr != IE_NONE ) {
rv = ERR_DESTROY_INTERFACE_ERROR;
return rv;
}
// done - success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: startmobileagent
*
***************************************************************************************/
TResult CSFacontroller::startmobileagent( TStartAgentRequest aArgs )
{
TResult rv;
int errcode;
TCAProcessError perr;
char command_line_str[MAXCOMMANDLINELENGTH];
TDCFError terr;
// 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;
return rv;
}
// do some semantic checking of the params
if( (aArgs.iSolicitationMode < -1) || (aArgs.iSolicitationMode > 1) ) {
rv.iServiceResult = ERR_INVALIDARG;
rv.iData0 = 3;
return rv;
}
if( (aArgs.iSolicitationMode == 1) && (aArgs.iSolicitationInterval < 1) ) {
rv.iServiceResult = ERR_INVALIDARG;
rv.iData0 = 4;
return rv;
}
if( aArgs.iSolicitationMode != 1 ) {
aArgs.iSolicitationInterval = 1;
}
// add the interface name to the config file
snprintf( command_line_str, MAXCOMMANDLINELENGTH, "%s 3 %d %d", aArgs.iLowerInterface, aArgs.iSolicitationMode, aArgs.iSolicitationInterval );
terr = iDynamicsConfigFile.AddListOption( "INTERFACES_BEGIN", "INTERFACES_END", command_line_str, &errcode );
if( terr != DCE_NONE ) {
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
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;
delete iAgentProcess;
iAgentProcess = NULL;
return rv;
}
iLowerInterface = aArgs.iLowerInterface;
// done - success
rv.iServiceResult = ERR_NONE;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: stopmobileagent
*
***************************************************************************************/
TResult CSFacontroller::stopmobileagent( int aArgs )
{
TResult rv;
TCAProcessError perr;
TProcessStatus pstatus;
TDCFError terr;
int errcode;
// 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;
}
// remove the interface line added in startup
terr = iDynamicsConfigFile.RemoveListOption( "INTERFACES_BEGIN", "INTERFACES_END", iLowerInterface.c_str(), &errcode );
if( terr != DCE_NONE ) {
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
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 CSFacontroller::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 CSFacontroller::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
rv.iServiceResult = ERR_NONE;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: removesingleoption
*
***************************************************************************************/
TResult CSFacontroller::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
rv.iServiceResult = ERR_NONE;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: addlistoption
*
***************************************************************************************/
TResult CSFacontroller::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
rv.iServiceResult = ERR_NONE;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: removelistoption
*
***************************************************************************************/
TResult CSFacontroller::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;
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
rv.iServiceResult = ERR_NONE;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: getstatus
*
***************************************************************************************/
TFaStatusInfo CSFacontroller::getstatus( int aArgs )
{
TFaStatusInfo rv;
TDynamicsCallInfo cres;
TForeignAgentStatusInfo foreign_agent_info;
// init the return value
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.ForeignAgentGetStatus( &foreign_agent_info );
if( cres.iResult != DC_SUCCESS ) {
set_dynamics_error( &(rv.iCallResult), &cres );
return rv;
}
// set the result
rv.iAdvertisementsSent = foreign_agent_info.iAdvertisementsSent;
rv.iDiscardedMalformed = foreign_agent_info.iDiscardedMalformed;
rv.iDiscardedUnknownExtension = foreign_agent_info.iDiscardedUnknownExtension;
rv.iDiscardedVendor = foreign_agent_info.iDiscardedVendor;
rv.iPendingRegistrationRequests = foreign_agent_info.iPendingRegistrationRequests;
rv.iReplysAccepted = foreign_agent_info.iReplysAccepted;
rv.iReplysRejected = foreign_agent_info.iReplysRejected;
rv.iRequestsAccepted = foreign_agent_info.iRequestsAccepted;
rv.iRequestsRejected = foreign_agent_info.iRequestsRejected;
rv.iTunnelCount = foreign_agent_info.iTunnelCount;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: destroytunnelid
*
***************************************************************************************/
TResult CSFacontroller::destroytunnelid( TFaTunnelID 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.ForeignAgentDestroyTunnel( aArgs.iMobileNodeAddress );
if( cres.iResult != DC_SUCCESS ) {
set_dynamics_error( &rv, &cres );
return rv;
}
// done
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: listtunnels
*
***************************************************************************************/
TFaTunnelList CSFacontroller::listtunnels( int aArgs )
{
TResult res;
TFaTunnelList rv = { 0, NULL };
TDynamicsCallInfo cres;
TTunnelID 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.ForeignAgentGetTunnels( &tunnel_count, tunnel_list );
if( cres.iResult != DC_SUCCESS ) {
return rv;
}
// allocate memory for the list
rv.TFaTunnelList_len = tunnel_count;
rv.TFaTunnelList_val = (TFaTunnelID*)calloc( tunnel_count, sizeof(TFaTunnelID) );
assert( rv.TFaTunnelList_val != NULL );
// now return the information
for( i = 0; i < tunnel_count; i++ ) {
(rv.TFaTunnelList_val)[i].iAgentID = 0;
(rv.TFaTunnelList_val)[i].iID = (tunnel_list[i]).iTunnelID;
(rv.TFaTunnelList_val)[i].iHomeAgentAddress = (tunnel_list[i]).iHomeAgentAddress;
(rv.TFaTunnelList_val)[i].iMobileNodeAddress = (tunnel_list[i]).iMobileNodeAddress;
}
// done - success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: gettunnelinfo
*
***************************************************************************************/
TFaTunnelInfo CSFacontroller::gettunnelinfo( TGetTunnelRequest aArgs )
{
TFaTunnelInfo rv;
TDynamicsCallInfo cres;
TForeignAgentTunnelInfo fati;
// 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.ForeignAgentGetTunnelInfo( aArgs.iMobileNodeAddress, &fati );
if( cres.iResult != DC_SUCCESS ) {
set_dynamics_error( &(rv.iCallResult), &cres );
return rv;
}
// set the info
rv.iCareofAddress = fati.iCareofAddress;
rv.iCreationTime = fati.iCreationTime;
rv.iExpirationTime = fati.iExpirationTime;
rv.iHomeAgentAddress = fati.iHomeAgentAddress;
rv.iLastTimestamp = fati.iLastTimestamp;
rv.iMobileNodeAddress = fati.iMobileNodeAddress;
rv.iPrivateHomeAgentID = fati.iPrivateHomeAgentID;
rv.iRefreshTime = fati.iRefreshTime;
rv.iSPI = fati.iSPI;
rv.iTimeout = fati.iTimeout;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: settimeout
*
***************************************************************************************/
void CSFacontroller::settimeout( TTimeoutRequest aArgs )
{
iDynamicsCallTimeout = aArgs.iTimeout;
iDynamicsCommand.SetTimeout( aArgs.iTimeout );
}
/****************************************************************************************
*
* PRIVATE FUNCTION: is_agent_running
*
***************************************************************************************/
TResult CSFacontroller::is_agent_running()
{
TResult rv;
TCAProcessError perr;
TProcessStatus pstatus;
// clear the rv
memset( &rv, 0, sizeof(rv) );
// 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 CSFacontroller::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;
}