/*
* 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.
* Wed Oct 01 09:46:52 2003
* System Includes
*
*/
#include <stdio.h>
#include <signal.h>
#ifndef WIN32
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
/****************************************************************************************
*
* Local Includes
*
***************************************************************************************/
#include "CSvcMncontroller.h"
#include "CSMncontroller.h"
#include "standard_unix.h"
#include "strncpynt.h"
/****************************************************************************************
*
* Definitions
*
***************************************************************************************/
#define TEMPLATE_CONFIG_FILE "dynmnd.template.conf"
#define MOBILE_AGENT_COMMAND_LINE "./dynmnd --fg --debug --config "
#define MAXCOMMANDLINELENGTH (31 + 256 + 1)
#define MAXFOREIGNAGENTCOUNT 32
#define MAXINTERFACECONFIGENTRY (IFNAMSIZ + 128)
/****************************************************************************************
*
* Implementation
*
***************************************************************************************/
CSMncontroller::CSMncontroller()
{
iDynamicsCallTimeout = -1;
iAgentProcess = NULL;
}
CSMncontroller::~CSMncontroller()
{
assert( iAgentProcess == NULL );
}
int CSMncontroller::GetKey()
{
return iKey;
}
void CSMncontroller::SetKey( int aKey )
{
iKey = aKey;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: cstr_createagent
*
***************************************************************************************/
TResult CSMncontroller::cstr_createagent( void )
{
TResult rv;
int errcode;
TDCFError terr;
// initialise the return value
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// create a local copy of the configuration file
terr = iDynamicsConfigFile.SetReferenceFile( TEMPLATE_CONFIG_FILE );
if( terr != DCE_NONE ) {
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
return rv;
}
terr = iDynamicsConfigFile.CreateLocalCopy( &errcode );
if( terr != DCE_NONE ) {
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
return rv;
}
// done - success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: dstr_removeagent
*
***************************************************************************************/
int CSMncontroller::dstr_removeagent( int aArgs, int *aDeleteInstance )
{
int rv = ERR_NONE, errcode;
TDCFError terr;
// make sure that the proces isn't running
if( iAgentProcess != NULL ) {
*aDeleteInstance = 0;
rv = ERR_INVALIDSTATE;
return rv;
}
// clean up the config file
terr = iDynamicsConfigFile.RemoveLocalCopy( &errcode );
if( terr != DCE_NONE ) {
rv = ERR_CONFIG_FILE_ERROR;
return rv;
}
// done - success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: startmobileagent
*
***************************************************************************************/
TResult CSMncontroller::startmobileagent( int aArgs )
{
TResult rv;
int errcode;
TCAProcessError perr;
char command_line_str[MAXCOMMANDLINELENGTH];
// initialise the return value
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;
}
// 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;
}
// done - success
rv.iServiceResult = ERR_NONE;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: stopmobileagent
*
***************************************************************************************/
TResult CSMncontroller::stopmobileagent( int aArgs )
{
TResult rv;
TCAProcessError perr;
TProcessStatus pstatus;
// initialise the return value
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 CSMncontroller::getmobileagentstatus( int aArgs )
{
TResult rv;
TCAProcessError perr;
TProcessStatus pstatus;
// init the rv - note that we include the result even though it is always ERR_NONE
// here because the stub may return an error
memset( &rv, 0, sizeof(rv) );
rv.iServiceResult = ERR_NONE;
// 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 CSMncontroller::setsingleoption( TOptionDesc aArgs )
{
TResult rv;
int errcode;
TDCFError cerr;
// initialise the return value
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 CSMncontroller::removesingleoption( TOptionDesc aArgs )
{
TResult rv;
int errcode;
TDCFError cerr;
// initialise the return value
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 CSMncontroller::addlistoption( TOptionDesc aArgs )
{
TResult rv;
int errcode;
TDCFError cerr;
// initialise the return value
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 CSMncontroller::removelistoption( TOptionDesc aArgs )
{
TResult rv;
int errcode;
TDCFError cerr;
// initialise the return value
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: getcareofaddress
*
***************************************************************************************/
TResult CSMncontroller::sethomeaddress( THomeAddressDesc aArgs )
{
TResult rv;
char dynamics_config[MAXINTERFACECONFIGENTRY];
struct in_addr home_address, home_network_address, home_agent_address;
TDCFError terr;
int errcode;
// initialise the return value
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;
}
// validate the arguments
if( aArgs.iHomeAddress == -1 ) {
rv.iServiceResult = ERR_INVALIDARG;
rv.iData0 = 2;
return rv;
}
if( (aArgs.iHomeAddressPrefix < 1) || (aArgs.iHomeAddressPrefix > 31) ) {
rv.iServiceResult = ERR_INVALIDARG;
rv.iData0 = 3;
return rv;
}
if( aArgs.iHomeAgentAddress == -1 ) {
rv.iServiceResult = ERR_INVALIDARG;
rv.iData0 = 4;
return rv;
}
// if the home address specified is zero, then we take this as meaning that the user
// wants to reset the interface back to it's original (PPP configured) address. This
// doesn't effect the entries in the configuration file at all
if( aArgs.iHomeAddress == 0 ) {
return rv;
}
// set the home address on the interface
rv = SetInterfaceAddress( aArgs.iInterfaceName, aArgs.iHomeAddress );
if( rv.iServiceResult != ERR_NONE ) {
return rv;
}
// set the home address in the dynamics config file
home_address.ADDRESS_INTEGER = aArgs.iHomeAddress;
snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "MNHomeIPAddress %s", inet_ntoa(home_address) );
terr = iDynamicsConfigFile.SetSingleOption( "MNHomeIPAddress", dynamics_config, &errcode );
if( terr != DCE_NONE ) {
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
rv.iData0 = errcode;
return rv;
}
// set the home network prefix in the dynamics config file
home_network_address = GetNetworkAddressFromHostAddress( aArgs.iHomeAddress, aArgs.iHomeAddressPrefix );
snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "HomeNetPrefix %s/%d", inet_ntoa(home_network_address), aArgs.iHomeAddressPrefix );
terr = iDynamicsConfigFile.SetSingleOption( "HomeNetPrefix", dynamics_config, &errcode );
if( terr != DCE_NONE ) {
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
rv.iData0 = errcode;
return rv;
}
// set the home agent address
home_agent_address.ADDRESS_INTEGER = aArgs.iHomeAgentAddress;
snprintf( dynamics_config, MAXINTERFACECONFIGENTRY, "HAIPAddress %s", inet_ntoa(home_agent_address) );
fprintf( stderr, "DEBUG: setting option '%s'\n", dynamics_config );
terr = iDynamicsConfigFile.SetSingleOption( "HAIPAddress", dynamics_config, &errcode );
if( terr != DCE_NONE ) {
rv.iServiceResult = ERR_CONFIG_FILE_ERROR;
rv.iSubComponentResult = (int)terr;
rv.iData0 = errcode;
return rv;
}
// done
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: getcareofaddress
*
***************************************************************************************/
TResult CSMncontroller::getcareofaddress( int aArgs )
{
TResult rv;
struct in_addr addr = { 0 };
TDynamicsCallInfo cres;
TCAProcessError perr;
TProcessStatus pstatus;
// initialise the return value
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// 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;
}
// use the dynamics command wrapper to make the call
cres = iDynamicsCommand.MobileNodeAgentGetCareofAddress( &addr );
// if the call failed then set the TResult correctly
if( cres.iResult != DC_SUCCESS ) {
rv.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iSubComponentResult = cres.iResult;
rv.iData0 = cres.iErrorCode;
rv.iData1 = cres.iErrorDetail;
return rv;
}
// otherwise pack up the successful return info
rv.iServiceResult = ERR_NONE;
rv.iData0 = addr.ADDRESS_INTEGER;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: getstatus
*
***************************************************************************************/
TMobileNodeStatus CSMncontroller::getstatus( int aArgs )
{
TMobileNodeStatus rv;
TCAProcessError perr;
TProcessStatus pstatus;
TDynamicsCallInfo cres;
TMobileNodeAgentStatusInfo mobile_node_status;
// init the return value
memset( &rv, 0, sizeof(rv) );
rv.iCallResult.iServiceResult = ERR_NONE;
// check that the agent was running
if( iAgentProcess == NULL ) {
rv.iCallResult.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.iCallResult.iServiceResult = ERR_INVALIDSTATE;
return rv;
}
// make the call
cres = iDynamicsCommand.MobileNodeAgentGetStatus( &mobile_node_status );
if( cres.iResult != DC_SUCCESS ) {
rv.iCallResult.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iCallResult.iSubComponentResult = cres.iResult;
rv.iCallResult.iData0 = cres.iErrorCode;
rv.iCallResult.iData1 = cres.iErrorDetail;
return rv;
}
// copy the data from mobile_node_status to the rv
rv.iColocatedAddress = mobile_node_status.iColocatedAddress;
rv.iConnected = mobile_node_status.iConnected;
rv.iForeignAgentAddress = mobile_node_status.iForeignAgentAddress;
rv.iHomeAddress = mobile_node_status.iHomeAddress;
rv.iHomeAgentAddress = mobile_node_status.iHomeAgentAddress;
memcpy( rv.iInfoText, mobile_node_status.iInfoText, X_MAXINFOLEN );
memcpy( rv.iLastErrorString, mobile_node_status.iLastErrorString, X_MAXERRORSTRING );
rv.iLifetimeRemaining = mobile_node_status.iLifetimeRemaining;
rv.iLocalAddress = mobile_node_status.iLocalAddress;
rv.iReplyCode = mobile_node_status.iReplyCode;
rv.iSecondsSinceLastReply = mobile_node_status.iSecondsSinceLastReply;
rv.iSecondsSinceLastRequest = mobile_node_status.iTunnelMode;
rv.iTunnelUp = mobile_node_status.iTunnelUp;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: connect
*
***************************************************************************************/
TResult CSMncontroller::connect( TTunnelingModeDesc aArgs )
{
TResult rv;
TDynamicsCallInfo cres;
TCAProcessError perr;
TProcessStatus pstatus;
// initialise the return value
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// 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;
}
// call the wrapper
cres = iDynamicsCommand.MobileNodeAgentConnect();
if( cres.iResult != DC_SUCCESS ) {
rv.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iSubComponentResult = cres.iResult;
rv.iData0 = cres.iErrorCode;
rv.iData1 = cres.iErrorDetail;
return rv;
}
// success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: disconnect
*
***************************************************************************************/
TResult CSMncontroller::disconnect( int aArgs )
{
TResult rv;
TDynamicsCallInfo cres;
TCAProcessError perr;
TProcessStatus pstatus;
// initialise the return value
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// 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;
}
// call the wrapper
cres = iDynamicsCommand.MobileNodeAgentDisconnect();
if( cres.iResult != DC_SUCCESS ) {
rv.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iSubComponentResult = cres.iResult;
rv.iData0 = cres.iErrorCode;
rv.iData1 = cres.iErrorDetail;
return rv;
}
// success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: confirm
*
***************************************************************************************/
TResult CSMncontroller::confirm( int aArgs )
{
TResult rv;
TDynamicsCallInfo cres;
TCAProcessError perr;
TProcessStatus pstatus;
// initialise the return value
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// 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;
}
// call the wrapper
cres = iDynamicsCommand.MobileNodeAgentConfirm();
if( cres.iResult != DC_SUCCESS ) {
rv.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iSubComponentResult = cres.iResult;
rv.iData0 = cres.iErrorCode;
rv.iData1 = cres.iErrorDetail;
return rv;
}
// success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: rescaninterfaces
*
***************************************************************************************/
TResult CSMncontroller::rescaninterfaces( int aArgs )
{
TResult rv;
TDynamicsCallInfo cres;
TCAProcessError perr;
TProcessStatus pstatus;
// initialise the return value
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// 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;
}
// call the wrapper
cres = iDynamicsCommand.MobileNodeAgentRescan();
if( cres.iResult != DC_SUCCESS ) {
rv.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iSubComponentResult = cres.iResult;
rv.iData0 = cres.iErrorCode;
rv.iData1 = cres.iErrorDetail;
return rv;
}
// success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: setfapolicy - aPolicyDesc is a bitfield with each bit representing
* a particular policy that should be turned on or off. The values for each
* policy are in the interface file (.x). We try and set the policy for each
* bit regardless of whether some calls fail. The result is the OR of all the
* results (i.e. if one fails the op fails). To get more info about which
* succeeded you can just call getpolicy.
*
***************************************************************************************/
TResult CSMncontroller::setfapolicy( TPolicyRequest aArgs )
{
TResult rv;
TDynamicsCallInfo cres;
TCAProcessError perr;
TProcessStatus pstatus;
// initialise the return value
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// 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;
}
// call the wrapper
cres = iDynamicsCommand.MobileNodeAgentSetPolicy( aArgs.iPolicy );
if( cres.iResult != DC_SUCCESS ) {
rv.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iSubComponentResult = cres.iResult;
rv.iData0 = cres.iErrorCode;
rv.iData1 = cres.iErrorDetail;
return rv;
}
// success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: getfapolicy
*
***************************************************************************************/
TResult CSMncontroller::getfapolicy( int aArgs )
{
TResult rv;
TDynamicsCallInfo cres;
int policy_vector;
TCAProcessError perr;
TProcessStatus pstatus;
// initialise the return value
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// 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;
}
// call the wrapper
cres = iDynamicsCommand.MobileNodeAgentGetPolicy( &policy_vector );
if( cres.iResult != DC_SUCCESS ) {
rv.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iSubComponentResult = cres.iResult;
rv.iData0 = cres.iErrorCode;
rv.iData1 = cres.iErrorDetail;
return rv;
}
// success
rv.iServiceResult = ERR_NONE;
rv.iData0 = policy_vector;
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: listforeignagents
*
***************************************************************************************/
TForeignAgentList CSMncontroller::listforeignagents( int aArgs )
{
TDynamicsCallInfo cres;
TCAProcessError perr;
TProcessStatus pstatus;
int foreign_agent_count = MAXFOREIGNAGENTCOUNT, i;
TMobileNodeForeignAgentInfo foreign_agent_list[MAXFOREIGNAGENTCOUNT];
TForeignAgentList rv = { 0, NULL };
// check that the agent was running
if( iAgentProcess == NULL ) {
return rv;
}
// check that the agent is still runnning
perr = iAgentProcess->GetProcessStatus( &pstatus );
assert( perr == CAE_NONE );
if( pstatus != PS_STARTED ) {
return rv;
}
// call the dynamics wrapper
cres = iDynamicsCommand.MobileNodeAgentGetForeignAgentList( &foreign_agent_count, foreign_agent_list);
if( cres.iResult != DC_SUCCESS ) {
return rv;
}
// allocate the memory
rv.TForeignAgentList_len = foreign_agent_count;
rv.TForeignAgentList_val = (TForeignAgentInfo*)calloc( foreign_agent_count, sizeof(TForeignAgentInfo) );
assert( rv.TForeignAgentList_val != NULL );
// copy the entries - all entries default to 0 due to calloc()
for( i = 0; i < foreign_agent_count; i++ ) {
(rv.TForeignAgentList_val)[i].iCallResult.iServiceResult = ERR_NONE;
(rv.TForeignAgentList_val)[i].iForeignAgentAddress = (foreign_agent_list[i]).iForeignAgentAddress;
(rv.TForeignAgentList_val)[i].iInterfaceIndex = (foreign_agent_list[i]).iInterfaceIndex;
(rv.TForeignAgentList_val)[i].iInUse = (foreign_agent_list[i]).iInUse;
(rv.TForeignAgentList_val)[i].iLastAdvertisement = (foreign_agent_list[i]).iLastAdvertisement;
(rv.TForeignAgentList_val)[i].iPriority = (foreign_agent_list[i]).iPriority;
memcpy( (rv.TForeignAgentList_val)[i].iInterfaceName, (foreign_agent_list[i]).iInterfaceName, X_MAXINTERFACENAMELEN );
memcpy( (rv.TForeignAgentList_val)[i].iNAI, (foreign_agent_list[i]).iNAI, X_MAXNAILEN );
}
// done - success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: getforeignagentinfo
*
***************************************************************************************/
TForeignAgentInfo CSMncontroller::getforeignagentinfo( TForeignAgentInfoRequest aArgs )
{
TDynamicsCallInfo cres;
TCAProcessError perr;
TProcessStatus pstatus;
TMobileNodeForeignAgentInfo foreign_agent_info;
TForeignAgentInfo rv;
// init the result
memset( &rv, 0, sizeof(rv) );
rv.iCallResult.iServiceResult = ERR_NONE;
// check that the agent was running
if( iAgentProcess == NULL ) {
rv.iCallResult.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.iCallResult.iServiceResult = ERR_INVALIDSTATE;
return rv;
}
// call the dynamics wrapper
cres = iDynamicsCommand.MobileNodeAgentGetForeignAgentInfo( aArgs.iForeignAgentID, &foreign_agent_info );
if( cres.iResult != DC_SUCCESS ) {
rv.iCallResult.iServiceResult = ERR_DYNAMICS_CALL_FAILED;
rv.iCallResult.iSubComponentResult = cres.iResult;
rv.iCallResult.iData0 = cres.iErrorCode;
rv.iCallResult.iData1 = cres.iErrorDetail;
return rv;
}
// set the result
rv.iForeignAgentAddress = foreign_agent_info.iForeignAgentAddress;
rv.iInterfaceIndex = foreign_agent_info.iInterfaceIndex;
rv.iInUse = foreign_agent_info.iInUse;
rv.iLastAdvertisement = foreign_agent_info.iLastAdvertisement;
rv.iPriority = foreign_agent_info.iPriority;
memcpy( rv.iInterfaceName, foreign_agent_info.iInterfaceName, X_MAXINTERFACENAMELEN );
memcpy( rv.iNAI, foreign_agent_info.iNAI, X_MAXNAILEN );
// done - success
return rv;
}
/****************************************************************************************
*
* PUBLIC FUNCTION: settimeout
*
***************************************************************************************/
void CSMncontroller::settimeout( TTimeoutRequest aArgs )
{
iDynamicsCallTimeout = aArgs.iTimeout;
iDynamicsCommand.SetTimeout( aArgs.iTimeout );
}
/****************************************************************************************
*
* PRIVATE FUNCTION: SetInterfaceAddress
*
***************************************************************************************/
TResult CSMncontroller::SetInterfaceAddress( char *aInterfaceName, int aAddress )
{
TResult rv;
int sockfd, err;
struct ifreq ifr;
struct sockaddr_in destination_address, *saddr;
// check parameters
assert( aInterfaceName );
// init the response
rv.iServiceResult = ERR_NONE;
rv.iSubComponentResult = 0;
rv.iData0 = 0;
rv.iData1 = 0;
// create a socket to make ioctl calls on
sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
if( sockfd <= 0 ) {
rv.iServiceResult = ERR_SET_INTERFACE_ADDRESS_ERROR;
rv.iSubComponentResult = SIE_SOCKET_FAILED;
rv.iData0 = errno;
return rv;
}
// setup the request
STRNCPY_NULL_TERMINATE( ifr.ifr_name, aInterfaceName, IFNAMSIZ );
// get the current pointopoint address
err = ioctl( sockfd, SIOCGIFDSTADDR, &ifr );
if( err == -1 ) {
rv.iServiceResult = ERR_SET_INTERFACE_ADDRESS_ERROR;
rv.iSubComponentResult = SIE_IOCTL_GET_DESTINATION_ADDRESS_FAILED;
rv.iData0 = errno;
return rv;
}
destination_address = (*((struct sockaddr_in*)(&(ifr.ifr_dstaddr))));
// set the interface address
saddr = (struct sockaddr_in*)(&(ifr.ifr_addr));
saddr->sin_family = AF_INET;
saddr->sin_port = 0;
saddr->sin_addr.ADDRESS_INTEGER = aAddress;
err = ioctl( sockfd, SIOCSIFADDR, &ifr );
if( err == -1 ) {
rv.iServiceResult = ERR_SET_INTERFACE_ADDRESS_ERROR;
rv.iSubComponentResult = SIE_IOCTL_SET_ADDRESS_FAILED;
rv.iData0 = errno;
return rv;
}
// setting the interface address seems to also set the the pointopoint (destination)
// address to the same thing, so set it back to what it was or routing won't work
saddr = (struct sockaddr_in*)(&(ifr.ifr_dstaddr));
*saddr = destination_address;
err = ioctl( sockfd, SIOCSIFDSTADDR, &ifr );
if( err == -1 ) {
rv.iServiceResult = ERR_SET_INTERFACE_ADDRESS_ERROR;
rv.iSubComponentResult = SIE_IOCTL_SET_DESTINATION_ADDRESS_FAILED;
rv.iData0 = errno;
return rv;
}
// done
return rv;
}
/****************************************************************************************
*
* PRIVATE FUNCTION: GetNetworkAddressFromHostAddress
*
***************************************************************************************/
struct in_addr CSMncontroller::GetNetworkAddressFromHostAddress( int aAddress, int aNetmask )
{
struct in_addr rv;
int netmask, i;
// create the netmask
for( netmask = 0, i = 0; i < aNetmask; i++ ) {
netmask |= 1<<(31-i);
}
// get the
rv.ADDRESS_INTEGER = ntohl( aAddress );
rv.ADDRESS_INTEGER &= netmask;
rv.ADDRESS_INTEGER = htonl( rv.ADDRESS_INTEGER );
// done
return rv;
}