testexecmgmt/ucc/Source/DynamicsCommandWrapper/CDynamicsCommand.cpp
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 * System Includes
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include <stdio.h>
       
    22 #include <assert.h>
       
    23 #include <string.h>
       
    24 #include <ctype.h>
       
    25 #ifndef WIN32
       
    26 #include <sys/socket.h>
       
    27 #include <netinet/in.h>
       
    28 #include <arpa/inet.h>
       
    29 #else
       
    30 #include <winsock2.h>
       
    31 #endif
       
    32 #include <stdlib.h>
       
    33 
       
    34 
       
    35 /****************************************************************************************
       
    36  * 
       
    37  * Local Includes
       
    38  * 
       
    39  ***************************************************************************************/
       
    40 #include "CDynamicsCommand.h"
       
    41 #include "../include/standard_unix.h"
       
    42 #include "../ProcessLibrary/proclib.h"
       
    43 #include "../include/strncpynt.h"
       
    44 
       
    45 
       
    46 /****************************************************************************************
       
    47  * 
       
    48  * Definitions
       
    49  * 
       
    50  ***************************************************************************************/
       
    51 #define HOME_AGENT_TOOL				"./dynha_tool"
       
    52 #define FOREIGN_AGENT_TOOL			"./dynfa_tool"
       
    53 #define MOBILE_NODE_AGENT_TOOL		        "./dynmn_tool"
       
    54 
       
    55 #define CALL_FAILED_PREFIX			"Call failed: "
       
    56 #define INVALID_ARGUMENTS_PREFIX	        "Invalid arguments. "
       
    57 #define CSH_FAILED_PREFIX                       "csh: "
       
    58 #define TARGET_NOT_FOUND                        "No such file" 
       
    59 #define FOREIGN_AGENT_DESTROY_TUNNEL_PREFIX     "Destroyed tunnel"
       
    60 #define MOBILE_AGENT_FOREIGN_AGENT_LIST_PREFIX  "List of heard mobility agents:"
       
    61 #define MOBILE_NODE_AGENT_SETPOLICY_PREFIX      "Set policy succeeded."
       
    62 #define MOBILE_NODE_AGENT_CONNECT_PREFIX        "Connect success."
       
    63 #define MOBILE_NODE_AGENT_DISCONNECT_PREFIX     "Disconnected"
       
    64 #define MOBILE_NODE_AGENT_CONFIRM_PREFIX        "Confirmed."
       
    65 #define CALL_FAILED_FUNCTION_NOT_PERMITTED      "function not permitted"
       
    66 #define CALL_FAILED_AGENT_UNREACHABLE           "agent unreachable"
       
    67 
       
    68 #define TOKENSIZE                               256
       
    69 #define MAX_TIMEOUT			        120000
       
    70 #define MIN_TIMEOUT				1
       
    71 
       
    72 
       
    73 /****************************************************************************************
       
    74  * 
       
    75  * Macro Functions
       
    76  * 
       
    77  ***************************************************************************************/
       
    78 #define IS_WHITESPACE(c)  (((c) == ' ')||((c) == '\t'))
       
    79 #define MIN(x,y)          (((x) < (y)) ? (x) : (y))
       
    80 
       
    81 
       
    82 /****************************************************************************************
       
    83  * 
       
    84  * File-scope static variables
       
    85  * 
       
    86  ***************************************************************************************/
       
    87 char *iTunnelModeString[] = { "no tunnel", "full tunnel", "triangle tunnel", "full tunnel direct to HA", NULL };
       
    88 char *iPolicyString[] = { "Early-expire", "Newest-FA", "Eager-switching", "Newest-ADV", NULL };
       
    89 
       
    90 
       
    91 /****************************************************************************************
       
    92  * 
       
    93  * PUBLIC METHOD: General
       
    94  * 
       
    95  ***************************************************************************************/
       
    96 CDynamicsCommand::CDynamicsCommand()
       
    97 {
       
    98 	iTimeout = MAX_TIMEOUT;
       
    99 }
       
   100 
       
   101 
       
   102 CDynamicsCommand::~CDynamicsCommand()
       
   103 {
       
   104 }
       
   105 
       
   106 
       
   107 void CDynamicsCommand::SetPipePath( string aPipePath )
       
   108 {
       
   109 	iPipePath = aPipePath;
       
   110 }
       
   111 
       
   112 
       
   113 void CDynamicsCommand::SetTimeout( int aTimeout )
       
   114 {
       
   115 	if( (aTimeout >= MIN_TIMEOUT) && (aTimeout <= MAX_TIMEOUT) ) {
       
   116 		iTimeout = aTimeout;
       
   117 	}
       
   118 }
       
   119 
       
   120 
       
   121 /****************************************************************************************
       
   122  * 
       
   123  * PUBLIC METHOD: ForeignAgentGetStatus
       
   124  * 
       
   125  ***************************************************************************************/
       
   126 TDynamicsCallInfo CDynamicsCommand::ForeignAgentGetStatus( TForeignAgentStatusInfo *aForeignAgentInfo )
       
   127 {
       
   128   TDynamicsCallInfo rv;
       
   129   string standard_output, standard_error;
       
   130   int res = 0;
       
   131 
       
   132   // check params
       
   133   assert( aForeignAgentInfo != NULL );
       
   134   
       
   135   // run the dynamics command line 
       
   136   rv = DynamicsCall( FOREIGN_AGENT_TOOL, "status", NULL, &standard_output, &standard_error );
       
   137   if( rv.iResult != DC_SUCCESS ) {
       
   138     return rv;
       
   139   }
       
   140 
       
   141   // parse the output 
       
   142   res |= GetIntegerEntry( standard_output.c_str(), "tunnels", &(aForeignAgentInfo->iTunnelCount) );
       
   143   res |= GetIntegerEntry( standard_output.c_str(), "pending reg.req.", &(aForeignAgentInfo->iPendingRegistrationRequests) );
       
   144   res |= GetIntegerEntry( standard_output.c_str(), "request rejected", &(aForeignAgentInfo->iRequestsRejected) );
       
   145   res |= GetIntegerEntry( standard_output.c_str(), "request accepted", &(aForeignAgentInfo->iRequestsAccepted) );
       
   146   res |= GetIntegerEntry( standard_output.c_str(), "reply accepted", &(aForeignAgentInfo->iReplysAccepted) );
       
   147   res |= GetIntegerEntry( standard_output.c_str(), "reply rejected", &(aForeignAgentInfo->iReplysRejected) );
       
   148   res |= GetIntegerEntry( standard_output.c_str(), "discard(unk. ext)", &(aForeignAgentInfo->iDiscardedUnknownExtension) );
       
   149   res |= GetIntegerEntry( standard_output.c_str(), "discard(malformed)", &(aForeignAgentInfo->iDiscardedMalformed) );
       
   150   res |= GetIntegerEntry( standard_output.c_str(), "discard(vendor)", &(aForeignAgentInfo->iDiscardedVendor) );
       
   151   res |= GetIntegerEntry( standard_output.c_str(), "advertisement sent", &(aForeignAgentInfo->iAdvertisementsSent) );
       
   152   
       
   153   // check for errors
       
   154   if( res != 0 ) {
       
   155     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   156   }
       
   157   
       
   158   // done
       
   159   return rv;
       
   160 }
       
   161 
       
   162 
       
   163 /****************************************************************************************
       
   164  * 
       
   165  * PUBLIC METHOD: ForeignAgentDestroyTunnel
       
   166  * 
       
   167  ***************************************************************************************/
       
   168 TDynamicsCallInfo CDynamicsCommand::ForeignAgentDestroyTunnel( unsigned int aMobileNodeAddress )
       
   169 {
       
   170   TDynamicsCallInfo rv;
       
   171   int match;
       
   172   string standard_output, standard_error;
       
   173   char *mnaddr;
       
   174   struct in_addr iaddr;
       
   175   char params[MAXCOMMANDLINE];
       
   176  
       
   177   // create the params string
       
   178   iaddr.ADDRESS_INTEGER = aMobileNodeAddress;
       
   179   mnaddr = inet_ntoa( iaddr );
       
   180   snprintf( params, MAXCOMMANDLINE, "%s", mnaddr );
       
   181 
       
   182   // run the dynamics command line 
       
   183   rv = DynamicsCall( FOREIGN_AGENT_TOOL, "destroy", params, &standard_output, &standard_error );
       
   184   if( rv.iResult != DC_SUCCESS ) {
       
   185     return rv;
       
   186   }
       
   187 
       
   188   // check for success - otherwise give general error
       
   189   match = strncmp( FOREIGN_AGENT_DESTROY_TUNNEL_PREFIX, standard_output.c_str(), strlen(FOREIGN_AGENT_DESTROY_TUNNEL_PREFIX) );
       
   190   if( match != 0 ) {
       
   191     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   192   }
       
   193   return rv;
       
   194 }
       
   195 
       
   196 
       
   197 /****************************************************************************************
       
   198  * 
       
   199  * PUBLIC METHOD: ForeignAgentGetTunnels
       
   200  * 
       
   201  ***************************************************************************************/
       
   202 TDynamicsCallInfo CDynamicsCommand::ForeignAgentGetTunnels( int *aTunnelCount, TTunnelID *aTunnelIDArray )
       
   203 {
       
   204   TDynamicsCallInfo rv;
       
   205   string standard_output, standard_error;
       
   206   int list_size;
       
   207 
       
   208   // check the params
       
   209   assert( aTunnelCount != NULL );
       
   210   assert( aTunnelIDArray != NULL );
       
   211   list_size = *aTunnelCount;
       
   212   *aTunnelCount = 0;
       
   213 
       
   214   // run the dynamics command line 
       
   215   rv = DynamicsCall( FOREIGN_AGENT_TOOL, "list", NULL, &standard_output, &standard_error );
       
   216   if( rv.iResult != DC_SUCCESS ) {
       
   217     return rv;
       
   218   }
       
   219 
       
   220   // parse the output and return
       
   221   rv =  ParseForeignAgentListOutput( standard_output, list_size, aTunnelIDArray, aTunnelCount );
       
   222   return rv;
       
   223 }
       
   224 
       
   225 
       
   226 /****************************************************************************************
       
   227  * 
       
   228  * PUBLIC METHOD: ForeignAgentGetTunnelInfo
       
   229  * 
       
   230  ***************************************************************************************/
       
   231 TDynamicsCallInfo CDynamicsCommand::ForeignAgentGetTunnelInfo( unsigned int aMobileNodeAddress, TForeignAgentTunnelInfo *aTunnelInfo )
       
   232 {
       
   233   TDynamicsCallInfo rv;
       
   234   string standard_output, standard_error;
       
   235   int res = 0;
       
   236   char params[MAXCOMMANDLINE];
       
   237   struct in_addr mobile_node_address;
       
   238 
       
   239   // check params
       
   240   assert( aTunnelInfo != NULL );
       
   241 
       
   242   // write the params
       
   243   mobile_node_address.ADDRESS_INTEGER = aMobileNodeAddress;
       
   244   snprintf( params, MAXCOMMANDLINE, " %s", inet_ntoa(mobile_node_address) );
       
   245 
       
   246   // run the dynamics command line 
       
   247   rv = DynamicsCall( FOREIGN_AGENT_TOOL, "show", params, &standard_output, &standard_error );
       
   248   if( rv.iResult != DC_SUCCESS ) {
       
   249     return rv;
       
   250   }
       
   251 
       
   252   // parse the output 
       
   253   res |= GetAddressEntry( standard_output.c_str(), "mobile addr", &(aTunnelInfo->iMobileNodeAddress) );
       
   254   res |= GetAddressEntry( standard_output.c_str(), "care-of addr", &(aTunnelInfo->iCareofAddress) );
       
   255   res |= GetAddressEntry( standard_output.c_str(), "home agent addr", &(aTunnelInfo->iHomeAgentAddress) );
       
   256   res |= GetIntegerEntry( standard_output.c_str(), "private HA id", &(aTunnelInfo->iPrivateHomeAgentID) );
       
   257   res |= GetDateEntry( standard_output.c_str(), "creation time", &(aTunnelInfo->iCreationTime) );
       
   258   res |= GetDateEntry( standard_output.c_str(), "expiration time", &(aTunnelInfo->iExpirationTime) );
       
   259   res |= GetDateEntry( standard_output.c_str(), "refresh time", &(aTunnelInfo->iRefreshTime) );
       
   260   res |= GetDateEntry( standard_output.c_str(), "last timestamp", &(aTunnelInfo->iLastTimestamp) );
       
   261   res |= GetIntegerEntry( standard_output.c_str(), "SPI", &(aTunnelInfo->iSPI) );
       
   262   res |= GetIntegerEntry( standard_output.c_str(), "timeout", &(aTunnelInfo->iTimeout) );
       
   263   
       
   264   // check for errors
       
   265   if( res != 0 ) {
       
   266     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   267   }
       
   268   
       
   269   // done
       
   270   return rv;
       
   271 }
       
   272 
       
   273 
       
   274 /****************************************************************************************
       
   275  * 
       
   276  * PUBLIC METHOD: HomeAgentGetStatus
       
   277  * 
       
   278  ***************************************************************************************/
       
   279 TDynamicsCallInfo CDynamicsCommand::HomeAgentGetStatus( THomeAgentStatusInfo *aHomeAgentInfo )
       
   280 {
       
   281   TDynamicsCallInfo rv;
       
   282   string standard_output, standard_error;
       
   283   int res = 0;
       
   284 
       
   285   // check params
       
   286   assert( aHomeAgentInfo != NULL );
       
   287   
       
   288   // run the dynamics command line 
       
   289   rv = DynamicsCall( HOME_AGENT_TOOL, "status", NULL, &standard_output, &standard_error );
       
   290   if( rv.iResult != DC_SUCCESS ) {
       
   291     return rv;
       
   292   }
       
   293 
       
   294   // parse the output 
       
   295   res |= GetIntegerEntry( standard_output.c_str(), "tunnels", &(aHomeAgentInfo->iTunnelCount) );
       
   296   res |= GetIntegerEntry( standard_output.c_str(), "request rejected", &(aHomeAgentInfo->iRequestsRejected) );
       
   297   res |= GetIntegerEntry( standard_output.c_str(), "request accepted", &(aHomeAgentInfo->iRequestsAccepted) );
       
   298   res |= GetIntegerEntry( standard_output.c_str(), "discard(unk. ext)", &(aHomeAgentInfo->iDiscardedUnknownExtension) );
       
   299   res |= GetIntegerEntry( standard_output.c_str(), "discard(malformed)", &(aHomeAgentInfo->iDiscardedMalformed) );
       
   300   res |= GetIntegerEntry( standard_output.c_str(), "discard(vendor)", &(aHomeAgentInfo->iDiscardedVendor) );
       
   301   res |= GetIntegerEntry( standard_output.c_str(), "advertisement sent", &(aHomeAgentInfo->iAdvertisementsSent) );
       
   302   
       
   303   // check for errors
       
   304   if( res != 0 ) {
       
   305     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   306   }
       
   307   
       
   308   // done
       
   309   return rv;
       
   310 }
       
   311 
       
   312 
       
   313 /****************************************************************************************
       
   314  * 
       
   315  * PUBLIC METHOD: HomeAgentDestroyTunnel
       
   316  * 
       
   317  ***************************************************************************************/
       
   318 TDynamicsCallInfo CDynamicsCommand::HomeAgentDestroyTunnel( unsigned int aMobileNodeAddress, unsigned int aHomeAgentAddress, 
       
   319 							    int aTunnelID )
       
   320 {
       
   321   TDynamicsCallInfo rv;
       
   322   int match;
       
   323   string standard_output, standard_error;
       
   324   char *mnaddr;
       
   325   struct in_addr iaddr;
       
   326   char params[MAXCOMMANDLINE];
       
   327 
       
   328   // create the params string
       
   329   iaddr.ADDRESS_INTEGER = aMobileNodeAddress;
       
   330   mnaddr = inet_ntoa( iaddr );
       
   331   snprintf( params, MAXCOMMANDLINE, "%s", mnaddr );
       
   332 
       
   333   // run the dynamics command line 
       
   334   rv = DynamicsCall( HOME_AGENT_TOOL, "destroy", params, &standard_output, &standard_error );
       
   335   if( rv.iResult != DC_SUCCESS ) {
       
   336     return rv;
       
   337   }
       
   338 
       
   339   // check for success - otherwise give general error
       
   340   match = strncmp( FOREIGN_AGENT_DESTROY_TUNNEL_PREFIX, standard_output.c_str(), strlen(FOREIGN_AGENT_DESTROY_TUNNEL_PREFIX) );
       
   341   if( match != 0 ) {
       
   342     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   343   }
       
   344   return rv;
       
   345 }
       
   346 
       
   347 
       
   348 /****************************************************************************************
       
   349  * 
       
   350  * PUBLIC METHOD: HomeAgentGetTunnels
       
   351  * 
       
   352  ***************************************************************************************/
       
   353 TDynamicsCallInfo CDynamicsCommand::HomeAgentGetTunnels( int *aTunnelCount, unsigned int *aMobileNodeAddresses )
       
   354 {
       
   355   TDynamicsCallInfo rv;
       
   356   string standard_output, standard_error;
       
   357   int list_size;
       
   358 
       
   359   // check the params
       
   360   assert( aTunnelCount != NULL );
       
   361   assert( aMobileNodeAddresses != NULL );
       
   362   list_size = *aTunnelCount;
       
   363   *aTunnelCount = 0;
       
   364 
       
   365   // run the dynamics command line 
       
   366   rv = DynamicsCall( HOME_AGENT_TOOL, "list", NULL, &standard_output, &standard_error );
       
   367   if( rv.iResult != DC_SUCCESS ) {
       
   368     return rv;
       
   369   }
       
   370 
       
   371   // parse the output and return
       
   372   rv =  ParseHomeAgentListOutput( standard_output, list_size, aMobileNodeAddresses, aTunnelCount );
       
   373   return rv;
       
   374 }
       
   375 
       
   376 
       
   377 /****************************************************************************************
       
   378  * 
       
   379  * PUBLIC METHOD: HomeAgentGetTunnelInfo
       
   380  * 
       
   381  ***************************************************************************************/
       
   382 TDynamicsCallInfo CDynamicsCommand::HomeAgentGetTunnelInfo( unsigned int aMobileNodeAddress, THomeAgentTunnelInfo *aTunnelInfo )
       
   383 {
       
   384   TDynamicsCallInfo rv;
       
   385   string standard_output, standard_error;
       
   386   int res = 0;
       
   387   char params[MAXCOMMANDLINE];
       
   388   struct in_addr mobile_node_address;
       
   389 
       
   390   // check params
       
   391   assert( aTunnelInfo != NULL );
       
   392 
       
   393   // write the params
       
   394   mobile_node_address.ADDRESS_INTEGER = aMobileNodeAddress;
       
   395   snprintf( params, MAXCOMMANDLINE, " %s", inet_ntoa(mobile_node_address) );
       
   396 
       
   397   // run the dynamics command line 
       
   398   rv = DynamicsCall( HOME_AGENT_TOOL, "show", params, &standard_output, &standard_error );
       
   399   if( rv.iResult != DC_SUCCESS ) {
       
   400     return rv;
       
   401   }
       
   402 
       
   403   // parse the output   
       
   404   res |= GetAddressEntry( standard_output.c_str(), "mobile addr", &(aTunnelInfo->iMobileNodeAddress) );
       
   405   res |= GetAddressEntry( standard_output.c_str(), "care-of addr", &(aTunnelInfo->iCareofAddress) );
       
   406   res |= GetAddressEntry( standard_output.c_str(), "home agent addr", &(aTunnelInfo->iHomeAgentAddress) );
       
   407   res |= GetDateEntry( standard_output.c_str(), "creation time", &(aTunnelInfo->iCreationTime) );
       
   408   res |= GetDateEntry( standard_output.c_str(), "expiration time", &(aTunnelInfo->iExpirationTime) );
       
   409   res |= GetDateEntry( standard_output.c_str(), "refresh time", &(aTunnelInfo->iRefreshTime) );
       
   410   res |= GetDateEntry( standard_output.c_str(), "last timestamp", &(aTunnelInfo->iLastTimestamp) );
       
   411   res |= GetIntegerEntry( standard_output.c_str(), "SPI", &(aTunnelInfo->iSPI) );
       
   412   res |= GetIntegerEntry( standard_output.c_str(), "timeout", &(aTunnelInfo->iTimeout) );
       
   413   
       
   414   // check for errors
       
   415   if( res != 0 ) {
       
   416     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   417   }
       
   418   
       
   419   // done
       
   420   return rv;
       
   421 }
       
   422 
       
   423 
       
   424 /****************************************************************************************
       
   425  * 
       
   426  * PUBLIC METHOD: MobileNodeAgentGetCareofAddress
       
   427  * 
       
   428  ***************************************************************************************/
       
   429 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentGetCareofAddress( struct in_addr *aCareofAddress )
       
   430 {
       
   431   TDynamicsCallInfo rv;
       
   432   string standard_output, standard_error;
       
   433   int res = 0;
       
   434   unsigned int addr;
       
   435 
       
   436   // check params
       
   437   assert( aCareofAddress != NULL );
       
   438 
       
   439   // run the dynamics command line 
       
   440   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "careof", NULL, &standard_output, &standard_error );
       
   441   if( rv.iResult != DC_SUCCESS ) {
       
   442     return rv;
       
   443   }
       
   444 
       
   445   // parse the output   
       
   446   res = GetAddressEntry( standard_output.c_str(), "Care-of address:", &addr );
       
   447   if( res != 0 ) {
       
   448     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   449   }
       
   450   aCareofAddress->s_addr = addr;
       
   451   return rv;
       
   452 }
       
   453 
       
   454 
       
   455 /****************************************************************************************
       
   456  * 
       
   457  * PUBLIC METHOD: MobileNodeAgentGetStatus
       
   458  * 
       
   459  ***************************************************************************************/
       
   460 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentGetStatus( TMobileNodeAgentStatusInfo *aMobileNodeAgentInfo )
       
   461 {
       
   462   TDynamicsCallInfo rv;
       
   463   string standard_output, standard_error;
       
   464   int res = 0;
       
   465   char buff[MAXCOMMANDLINE];
       
   466   // check params
       
   467   assert( aMobileNodeAgentInfo != NULL );
       
   468   
       
   469   // run the dynamics command line 
       
   470   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "status", NULL, &standard_output, &standard_error );
       
   471   if( rv.iResult != DC_SUCCESS ) {
       
   472     return rv;
       
   473   }
       
   474 
       
   475   // parse the output 
       
   476   res |= GetStringEntry( standard_output.c_str(), "state", buff, MAXCOMMANDLINE );
       
   477   res |= CheckMatchAsBoolean( buff, "Connected", &(aMobileNodeAgentInfo->iConnected) );
       
   478   res |= GetStringEntry( standard_output.c_str(), "tunnel is", buff, MAXCOMMANDLINE );
       
   479   res |= CheckMatchAsBoolean( buff, "up", &(aMobileNodeAgentInfo->iTunnelUp) );
       
   480   res |= GetAddressEntry( standard_output.c_str(), "local addr", &(aMobileNodeAgentInfo->iLocalAddress) );
       
   481   res |= GetAddressEntry( standard_output.c_str(), "co-addr", &(aMobileNodeAgentInfo->iColocatedAddress) );
       
   482   res |= GetAddressEntry( standard_output.c_str(), "FA-addr", &(aMobileNodeAgentInfo->iForeignAgentAddress) );
       
   483   res |= GetAddressEntry( standard_output.c_str(), "HA-addr", &(aMobileNodeAgentInfo->iHomeAgentAddress) );
       
   484   res |= GetAddressEntry( standard_output.c_str(), "Home addr", &(aMobileNodeAgentInfo->iHomeAddress) );
       
   485   res |= GetStringEntry( standard_output.c_str(), "info text", aMobileNodeAgentInfo->iInfoText, MAXINFOLEN );
       
   486   res |= GetStringEntry( standard_output.c_str(), "tunneling mode", buff, MAXCOMMANDLINE );
       
   487   res |= ConvertTunnelStringToInteger( buff, &(aMobileNodeAgentInfo->iTunnelMode) );
       
   488 
       
   489   // the following are optional - they only appear in the output when we have a connection
       
   490   GetStringEntry( standard_output.c_str(), "last warning", aMobileNodeAgentInfo->iLastErrorString, MAXERRORSTRING );
       
   491   GetIntegerEntry( standard_output.c_str(), "reply code", &(aMobileNodeAgentInfo->iReplyCode) );
       
   492   GetIntegerEntry( standard_output.c_str(), "lifetime left", &(aMobileNodeAgentInfo->iLifetimeRemaining) );
       
   493   GetIntegerEntry( standard_output.c_str(), "last request", &(aMobileNodeAgentInfo->iSecondsSinceLastRequest) );
       
   494   GetIntegerEntry( standard_output.c_str(), "last reply", &(aMobileNodeAgentInfo->iSecondsSinceLastReply) );
       
   495   
       
   496   // check for errors
       
   497   if( res != 0 ) {
       
   498     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   499   }
       
   500   
       
   501   // done
       
   502   return rv;
       
   503 }
       
   504 
       
   505 
       
   506 /****************************************************************************************
       
   507  * 
       
   508  * PUBLIC METHOD: MobileNodeAgentConnect
       
   509  * 
       
   510  ***************************************************************************************/
       
   511 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentConnect()
       
   512 {
       
   513   TDynamicsCallInfo rv;
       
   514   string standard_output, standard_error;
       
   515   int match;
       
   516 
       
   517   // run the dynamics command line 
       
   518   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "connect", NULL, &standard_output, &standard_error );
       
   519   if( rv.iResult != DC_SUCCESS ) {
       
   520     return rv;
       
   521   }
       
   522 
       
   523   // check output
       
   524   match = strncmp( MOBILE_NODE_AGENT_CONNECT_PREFIX, standard_output.c_str(), strlen(MOBILE_NODE_AGENT_CONNECT_PREFIX) );
       
   525   if( match != 0 ) {
       
   526     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   527     STRNCPY_NULL_TERMINATE( rv.iDynamicsErrorString, standard_output.c_str(), MAXIMUMERRORSTRINGLENGTH );
       
   528   }
       
   529   return rv;
       
   530 }
       
   531 
       
   532 
       
   533 /****************************************************************************************
       
   534  * 
       
   535  * PUBLIC METHOD: MobileNodeAgentDisconnect
       
   536  * 
       
   537  ***************************************************************************************/
       
   538 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentDisconnect()
       
   539 {
       
   540   TDynamicsCallInfo rv;
       
   541   string standard_output, standard_error;
       
   542   int match;
       
   543 
       
   544   // run the dynamics command line 
       
   545   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "disconnect", NULL, &standard_output, &standard_error );
       
   546   if( rv.iResult != DC_SUCCESS ) {
       
   547     return rv;
       
   548   }
       
   549 
       
   550   // check output
       
   551   match = strncmp( MOBILE_NODE_AGENT_DISCONNECT_PREFIX, standard_output.c_str(), strlen(MOBILE_NODE_AGENT_DISCONNECT_PREFIX) );
       
   552   if( match != 0 ) {
       
   553     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   554   }
       
   555   return rv;
       
   556 }
       
   557 
       
   558 
       
   559 /****************************************************************************************
       
   560  * 
       
   561  * PUBLIC METHOD: MobileNodeAgentConfirm
       
   562  * 
       
   563  ***************************************************************************************/
       
   564 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentConfirm()
       
   565 {
       
   566   TDynamicsCallInfo rv;
       
   567   string standard_output, standard_error;
       
   568   int match;
       
   569 
       
   570   // run the dynamics command line 
       
   571   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "confirm", NULL, &standard_output, &standard_error );
       
   572   if( rv.iResult != DC_SUCCESS ) {
       
   573     return rv;
       
   574   }
       
   575 
       
   576   // check output
       
   577   match = strncmp( MOBILE_NODE_AGENT_CONFIRM_PREFIX, standard_output.c_str(), strlen(MOBILE_NODE_AGENT_CONFIRM_PREFIX) );
       
   578   if( match != 0 ) {
       
   579     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   580   }
       
   581   return rv;
       
   582 }
       
   583 
       
   584 
       
   585 /****************************************************************************************
       
   586  * 
       
   587  * PUBLIC METHOD: MobileNodeAgentRescan
       
   588  * 
       
   589  ***************************************************************************************/
       
   590 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentRescan()
       
   591 {
       
   592   TDynamicsCallInfo rv;
       
   593   string standard_output, standard_error;
       
   594 
       
   595   // run the dynamics command line 
       
   596   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "rescan", NULL, &standard_output, &standard_error );
       
   597   if( rv.iResult != DC_SUCCESS ) {
       
   598     return rv;
       
   599   }
       
   600   return rv;
       
   601 }
       
   602 
       
   603 
       
   604 /****************************************************************************************
       
   605  * 
       
   606  * PUBLIC METHOD: MobileNodeAgentSetPolicy
       
   607  * 
       
   608  ***************************************************************************************/
       
   609 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentSetPolicy( int aPolicyVector )
       
   610 {
       
   611   TDynamicsCallInfo rv, res;
       
   612   string standard_output, standard_error;
       
   613   char params[MAXCOMMANDLINE];
       
   614   int i, match;
       
   615 
       
   616   // init the rv to success
       
   617   memset( &rv, 0, sizeof(rv) );
       
   618   rv.iResult = DC_SUCCESS;  
       
   619 
       
   620   // we can only set one policy at a time - so set each time
       
   621   for( i = 0; iPolicyString[i] != NULL; i++ ) { 
       
   622 
       
   623     // set the parameter string
       
   624     snprintf( params, MAXCOMMANDLINE, " %s %s", iPolicyString[i], ((aPolicyVector&(1<<i)) ? "on" : "off") );
       
   625 
       
   626     // run the dynamics command line
       
   627     res = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "policy", params, &standard_output, &standard_error );
       
   628 
       
   629     // check output
       
   630     match = strncmp( MOBILE_NODE_AGENT_SETPOLICY_PREFIX, standard_output.c_str(), strlen(MOBILE_NODE_AGENT_SETPOLICY_PREFIX) );
       
   631     if( match != 0 ) {
       
   632       res.iResult = DC_UNEXPECTED_OUTPUT;
       
   633     }
       
   634 
       
   635     // return the first error
       
   636     if( (res.iResult != DC_SUCCESS) && (rv.iResult == DC_SUCCESS) ) {
       
   637       rv = res;
       
   638       rv.iErrorDetail = i;
       
   639     }
       
   640   }
       
   641 
       
   642   // done
       
   643   return rv;
       
   644 }
       
   645 
       
   646 
       
   647 /****************************************************************************************
       
   648  * 
       
   649  * PUBLIC METHOD: MobileNodeAgentGetPolicy
       
   650  * 
       
   651  ***************************************************************************************/
       
   652 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentGetPolicy( int *aPolicyVector )
       
   653 {
       
   654   TDynamicsCallInfo rv;
       
   655   string standard_output, standard_error;
       
   656   int res, on, i;
       
   657 
       
   658   // check the params
       
   659   assert( aPolicyVector != NULL );
       
   660   *aPolicyVector = 0;
       
   661   memset( &rv, 0, sizeof(rv) );
       
   662   
       
   663   // run the dynamics command line 
       
   664   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "policy", NULL, &standard_output, &standard_error );
       
   665   if( rv.iResult != DC_SUCCESS ) {
       
   666     return rv;
       
   667   }
       
   668 
       
   669   // parse the output
       
   670   for( i = 0; iPolicyString[i] != NULL; i++ ) {
       
   671     res = GetPolicyEntry( standard_output.c_str(), iPolicyString[i], &on );
       
   672     if( res != 0 ) {
       
   673       rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   674       return rv;
       
   675     }
       
   676     if( on != 0 ) {
       
   677       (*aPolicyVector) |= (1<<i);
       
   678     }
       
   679   } 
       
   680 
       
   681   // done
       
   682   rv.iResult = DC_SUCCESS;
       
   683   return rv;
       
   684 }
       
   685 
       
   686 
       
   687 /****************************************************************************************
       
   688  * 
       
   689  * PUBLIC METHOD: MobileNodeAgentGetForeignAgentList
       
   690  * 
       
   691  ***************************************************************************************/
       
   692 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentGetForeignAgentList( int *aListCount, 
       
   693 									TMobileNodeForeignAgentInfo *aForeignAgentInfoList )
       
   694 {
       
   695   TDynamicsCallInfo rv;
       
   696   string standard_output, standard_error;
       
   697   int list_size;
       
   698 
       
   699   // check params 
       
   700   assert( aListCount != NULL );
       
   701   assert( aForeignAgentInfoList != NULL );
       
   702   list_size = *aListCount;
       
   703   *aListCount = 0;
       
   704 
       
   705   // init the list
       
   706   memset( aForeignAgentInfoList, 0, (sizeof(*aForeignAgentInfoList)*list_size) );
       
   707 
       
   708   // run the dynamics command line 
       
   709   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "list", NULL, &standard_output, &standard_error );
       
   710   if( rv.iResult != DC_SUCCESS ) {
       
   711     return rv;
       
   712   }
       
   713 
       
   714   // parse the output
       
   715   rv = ParseMobileNodeAgentListOutput( standard_output, list_size, aForeignAgentInfoList, aListCount );
       
   716   return rv;
       
   717 }
       
   718 
       
   719 
       
   720 /****************************************************************************************
       
   721  * 
       
   722  * PUBLIC METHOD: MobileNodeAgentGetForeignAgentInfo
       
   723  * 
       
   724  ***************************************************************************************/
       
   725 TDynamicsCallInfo CDynamicsCommand::MobileNodeAgentGetForeignAgentInfo( unsigned int aFAAddress, 
       
   726 									TMobileNodeForeignAgentInfo *aForeignAgentInfo )
       
   727 { 
       
   728   TDynamicsCallInfo rv;
       
   729   string standard_output, standard_error;
       
   730   int res = 0;
       
   731   char params[MAXCOMMANDLINE];
       
   732   struct in_addr foreign_agent_address;
       
   733 
       
   734   // check params
       
   735   assert( aForeignAgentInfo != NULL );
       
   736   memset( aForeignAgentInfo, 0, sizeof(*aForeignAgentInfo) );
       
   737 
       
   738   // write the params
       
   739   foreign_agent_address.ADDRESS_INTEGER = aFAAddress;
       
   740   snprintf( params, MAXCOMMANDLINE, " %s", inet_ntoa(foreign_agent_address) );
       
   741 
       
   742   // run the dynamics command line 
       
   743   rv = DynamicsCall( MOBILE_NODE_AGENT_TOOL, "show", params, &standard_output, &standard_error );
       
   744   if( rv.iResult != DC_SUCCESS ) {
       
   745     return rv;
       
   746   }
       
   747 
       
   748   // parse the output 
       
   749   res |= GetAddressEntry( standard_output.c_str(), "FA", &(aForeignAgentInfo->iForeignAgentAddress) );
       
   750   res |= GetStringEntry( standard_output.c_str(), "Interface", aForeignAgentInfo->iInterfaceName, MAXINTERFACENAME );
       
   751   res |= GetIntegerEntry( standard_output.c_str(), "Priority", &(aForeignAgentInfo->iPriority) );
       
   752   aForeignAgentInfo->iInUse = 1;
       
   753   res |= GetIntegerEntry( standard_output.c_str(), "Interface index", &(aForeignAgentInfo->iInterfaceIndex) );
       
   754   res |= GetIntegerEntry( standard_output.c_str(), "Last adv.", &(aForeignAgentInfo->iInterfaceIndex) );
       
   755   res |= GetStringEntry( standard_output.c_str(), "NAI", aForeignAgentInfo->iNAI, MAXNAILEN );
       
   756 
       
   757   
       
   758   // check for errors
       
   759   if( res != 0 ) {
       
   760     rv.iResult = DC_UNEXPECTED_OUTPUT;
       
   761   }
       
   762   
       
   763   // done
       
   764   return rv;
       
   765 
       
   766 }
       
   767 
       
   768 
       
   769 /****************************************************************************************
       
   770  * 
       
   771  * SECTION: HELPERS
       
   772  * 
       
   773  ***************************************************************************************/
       
   774 
       
   775 /****************************************************************************************
       
   776  * 
       
   777  * PRIVATE METHOD: GetDateEntry
       
   778  * 
       
   779  ***************************************************************************************/
       
   780 int CDynamicsCommand::GetDateEntry( const char *aOutput, const char *aLabel, int *aValue )
       
   781 {
       
   782   char *ptr;
       
   783   struct tm stime;
       
   784   time_t ttime;
       
   785 
       
   786   // check params
       
   787   assert( aOutput != NULL );
       
   788   assert( aLabel != NULL );
       
   789   assert( aValue != NULL );
       
   790 
       
   791   // set default
       
   792   *aValue = 0;
       
   793 
       
   794   // look for the label in the output
       
   795   ptr = strstr( aOutput, aLabel );
       
   796   if( ptr == NULL ) {
       
   797     return -1;
       
   798   }
       
   799 
       
   800   // skip over any spaces
       
   801   ptr += strlen(aLabel);
       
   802   for( ; IS_WHITESPACE(*ptr); ptr++ ) 
       
   803     ;
       
   804 
       
   805   // convert the string address into an int
       
   806   strptime( ptr, "%A %B %d %H:%M:%S %Y", &stime );
       
   807   ttime = mktime( &stime );
       
   808   *aValue = ttime;
       
   809   return 0;
       
   810 }
       
   811 
       
   812 
       
   813 /****************************************************************************************
       
   814  * 
       
   815  * PRIVATE METHOD: GetAddressEntry
       
   816  * 
       
   817  ***************************************************************************************/
       
   818 int CDynamicsCommand::GetAddressEntry( const char *aOutput, const char *aLabel, unsigned int *aValue )
       
   819 {
       
   820   int err;
       
   821   char *ptr;
       
   822   struct in_addr iaddr;
       
   823 
       
   824   // check params
       
   825   assert( aOutput != NULL );
       
   826   assert( aLabel != NULL );
       
   827   assert( aValue != NULL );
       
   828 
       
   829   // set default
       
   830   *aValue = 0;
       
   831 
       
   832   // look for the label in the output
       
   833   ptr = strstr( aOutput, aLabel );
       
   834   if( ptr == NULL ) {
       
   835     return -1;
       
   836   }
       
   837 
       
   838   // skip over any spaces
       
   839   ptr += strlen(aLabel);
       
   840   for( ; IS_WHITESPACE(*ptr); ptr++ ) 
       
   841     ;
       
   842 
       
   843   // if the current char is no a digit then there is a problem
       
   844   if( !isdigit(*ptr) ) {
       
   845     return -1;
       
   846   }
       
   847 
       
   848   // convert the string address into an in_addr 
       
   849   err = inet_aton( ptr, &iaddr );
       
   850   if( err == 0 ) {
       
   851     return -1;
       
   852   }
       
   853   *aValue = iaddr.ADDRESS_INTEGER;
       
   854   return 0;
       
   855 }
       
   856 
       
   857 
       
   858 /****************************************************************************************
       
   859  * 
       
   860  * PRIVATE METHOD: GetIntegerEntry
       
   861  * 
       
   862  ***************************************************************************************/
       
   863 int CDynamicsCommand::GetIntegerEntry( const char *aOutput, const char *aLabel, int *aValue )
       
   864 {
       
   865   char *ptr;
       
   866 
       
   867   // check params
       
   868   assert( aOutput != NULL );
       
   869   assert( aLabel != NULL );
       
   870   assert( aValue != NULL );
       
   871 
       
   872   // set the default value
       
   873   *aValue = 0;
       
   874 
       
   875   // look for the label in the output
       
   876   ptr = strstr( aOutput, aLabel );
       
   877   if( ptr == NULL ) {
       
   878     return -1;
       
   879   }
       
   880 
       
   881   // skip over any spaces
       
   882   ptr += strlen(aLabel);
       
   883   for( ; IS_WHITESPACE(*ptr); ptr++ ) 
       
   884     ;
       
   885 
       
   886   // if the current char is no a digit then there is a problem
       
   887   if( (!isdigit(*ptr)) && ((*ptr) != '-') ) {
       
   888     return -1;
       
   889   }
       
   890 
       
   891   // otherwise return the integer
       
   892   *aValue = atoi(ptr);
       
   893   return 0;
       
   894 }
       
   895 
       
   896 
       
   897 /****************************************************************************************
       
   898  * 
       
   899  * PRIVATE METHOD: GetPolicyEntry
       
   900  * 
       
   901  ***************************************************************************************/
       
   902 int CDynamicsCommand::GetPolicyEntry( const char *aOutput, const char *aLabel, int *aValue )
       
   903 {
       
   904   char *ptr;
       
   905 
       
   906   // check params
       
   907   assert( aOutput != NULL );
       
   908   assert( aLabel != NULL );
       
   909   assert( aValue != NULL );
       
   910 
       
   911   // set the default
       
   912   *aValue = 0;
       
   913 
       
   914   // look for the label in the output
       
   915   ptr = strstr( aOutput, aLabel );
       
   916   if( ptr == NULL ) {
       
   917     return -1;
       
   918   }
       
   919 
       
   920   // skip over any spaces
       
   921   ptr += strlen(aLabel);
       
   922   for( ; IS_WHITESPACE(*ptr); ptr++ ) 
       
   923     ;
       
   924 
       
   925   // if the string is not 'ON' or 'OFF' then we are confused
       
   926   if( (ptr[0] != 'O') || ((ptr[1] != 'N') && (ptr[1] != 'F')) ) {
       
   927     return -1;
       
   928   }
       
   929 
       
   930   // this should either be OFF => O or ON => 1
       
   931   *aValue = ((ptr[1] == 'N') ? 1 : 0);
       
   932   return 0;
       
   933 }
       
   934 
       
   935 
       
   936 /****************************************************************************************
       
   937  * 
       
   938  * PRIVATE METHOD: GetStringEntry
       
   939  * 
       
   940  ***************************************************************************************/
       
   941 int CDynamicsCommand::GetStringEntry( const char *aOutput, const char *aLabel, char *aValue, int aBufferSize  )
       
   942 {
       
   943   char *ptr, *start, *end;
       
   944   int string_length;
       
   945 
       
   946   // check params
       
   947   assert( aOutput != NULL );
       
   948   assert( aLabel != NULL );
       
   949   assert( aValue != NULL );
       
   950   assert( aBufferSize > 0 );
       
   951 
       
   952   // set the default
       
   953   aValue[0] = 0;
       
   954 
       
   955   // look for the label in the output
       
   956   ptr = strstr( aOutput, aLabel );
       
   957   if( ptr == NULL ) {
       
   958     return -1;
       
   959   }
       
   960 
       
   961   // skip over any spaces
       
   962   ptr += strlen(aLabel);
       
   963   for( ; IS_WHITESPACE(*ptr); ptr++ ) 
       
   964     ;
       
   965 
       
   966   // get the length of the substr to copy - don't copy the newline
       
   967   start = ptr;
       
   968   end = strchr( start, '\n' );
       
   969   if( end == NULL ) {
       
   970     end = strchr( start, 0 );
       
   971   }
       
   972   string_length = end - start;
       
   973   string_length = MIN( string_length, (aBufferSize-1) );
       
   974   
       
   975   // now copy the string and return
       
   976   memcpy( aValue, start, string_length );
       
   977   aValue[string_length] = 0;
       
   978   return 0;
       
   979 }
       
   980 
       
   981 
       
   982 /****************************************************************************************
       
   983  * 
       
   984  * PRIVATE METHOD: ParseForeignAgentListOutput: Parse ((IP_ADDR + SPACE + IP_ADDR + SPACE + INTEGER + '\n')* + '\n')
       
   985  * 
       
   986  ***************************************************************************************/
       
   987 TDynamicsCallInfo CDynamicsCommand::ParseForeignAgentListOutput( string aOutput, int aListSize, TTunnelID *aTunnelIDArray, int *aListCount )
       
   988 {
       
   989   TDynamicsCallInfo rv;
       
   990   const char *cline, *mobile_node_address_str, *home_agent_address_str, *tunnel_id_str;
       
   991   int tunnel_id, err;
       
   992   struct in_addr mobile_node_address, home_agent_address;
       
   993 
       
   994   // intialise the result
       
   995   memset( &rv, 0, sizeof(rv) );
       
   996   rv.iResult = DC_SUCCESS;
       
   997 
       
   998   // parse a line at a time
       
   999   cline = aOutput.c_str();
       
  1000   while( 1 ) {
       
  1001     
       
  1002     // check for end of output 
       
  1003     if( (cline == NULL) || (*cline == 0) || (*cline == '\n') ) {
       
  1004       break;
       
  1005     }
       
  1006 
       
  1007     // check for full output buffer
       
  1008     if( (*aListCount) == aListSize ) {
       
  1009       break;
       
  1010     }
       
  1011 
       
  1012     // otherwise go and find the tokens
       
  1013     mobile_node_address_str = cline;
       
  1014     home_agent_address_str = strchr( mobile_node_address_str, ' ' );
       
  1015     if( home_agent_address_str == NULL ) {
       
  1016       rv.iResult = DC_UNEXPECTED_OUTPUT;
       
  1017       break;
       
  1018     }
       
  1019     home_agent_address_str++;
       
  1020     tunnel_id_str = strchr( home_agent_address_str, ' ' );
       
  1021     if( tunnel_id_str == NULL ) {
       
  1022       rv.iResult = DC_UNEXPECTED_OUTPUT;
       
  1023       break;
       
  1024     }
       
  1025     tunnel_id_str++;
       
  1026 
       
  1027     // try and convert these into the correct format
       
  1028     err = inet_aton( mobile_node_address_str, &mobile_node_address );
       
  1029     if( err == 0 ) {
       
  1030       rv.iResult = DC_UNEXPECTED_OUTPUT;
       
  1031       break;
       
  1032     }
       
  1033     err = inet_aton( home_agent_address_str, &home_agent_address );
       
  1034     if( err == 0 ) {
       
  1035       rv.iResult = DC_UNEXPECTED_OUTPUT;
       
  1036       break;
       
  1037     }
       
  1038     tunnel_id = atoi( tunnel_id_str );
       
  1039 
       
  1040     // now place these into the output array
       
  1041     (aTunnelIDArray[*aListCount]).iMobileNodeAddress = mobile_node_address.ADDRESS_INTEGER;
       
  1042     (aTunnelIDArray[*aListCount]).iHomeAgentAddress = home_agent_address.ADDRESS_INTEGER;
       
  1043     (aTunnelIDArray[*aListCount]).iTunnelID = tunnel_id;
       
  1044     (*aListCount) += 1;
       
  1045 
       
  1046     // finally, update the 
       
  1047     cline = strchr( cline, '\n' );
       
  1048     if( cline == NULL ) {
       
  1049       break;
       
  1050     }
       
  1051     cline++;
       
  1052   }
       
  1053     
       
  1054   // done 
       
  1055   return rv;
       
  1056 }
       
  1057 
       
  1058 
       
  1059 /****************************************************************************************
       
  1060  * 
       
  1061  * PRIVATE METHOD: ParseHomeAgentListOutput: Parse: (X tunnels:\n(IP_ADDR+\n)*\n)
       
  1062  * 
       
  1063  ***************************************************************************************/
       
  1064 TDynamicsCallInfo CDynamicsCommand::ParseHomeAgentListOutput( string aOutput, int aListSize, unsigned int *aTunnelList, int *aListCount )
       
  1065 {
       
  1066   TDynamicsCallInfo rv;
       
  1067   const char *cline;
       
  1068   int err, i;
       
  1069   struct in_addr saddr;
       
  1070 
       
  1071   // check params
       
  1072   assert( aListCount != NULL );
       
  1073   assert( aTunnelList != NULL );
       
  1074   *aListCount = 0;
       
  1075 
       
  1076   // initialise the result
       
  1077   memset( &rv, 0, sizeof(rv) );
       
  1078   rv.iResult = DC_SUCCESS;
       
  1079 
       
  1080   // now parse each line
       
  1081   for( cline = aOutput.c_str(), i = 0; i < aListSize; i++ ) {
       
  1082 
       
  1083     // if this line starts with a newline then we are at the end
       
  1084     if( (cline == NULL) || (*cline == 0) || (*cline == '\n') ) {
       
  1085       break;
       
  1086     }
       
  1087     
       
  1088     // get the IP address of the mobile node
       
  1089     err = inet_aton( cline, &saddr );
       
  1090     if( err == 0 ) {
       
  1091       rv.iResult = DC_UNEXPECTED_OUTPUT;
       
  1092       break;
       
  1093     }
       
  1094     
       
  1095     // store this in the list
       
  1096     aTunnelList[(*aListCount)] = saddr.s_addr;
       
  1097     (*aListCount)++;
       
  1098 
       
  1099     // now move to the next line
       
  1100     cline = strchr( cline, '\n' );
       
  1101     if( cline == NULL ) {
       
  1102       break;
       
  1103     }
       
  1104     cline++;
       
  1105   }
       
  1106     
       
  1107     
       
  1108   // done 
       
  1109   return rv;
       
  1110 }
       
  1111 
       
  1112 
       
  1113 /****************************************************************************************
       
  1114  * 
       
  1115  * PRIVATE METHOD: ParseMobileNodeAgentListOutput: 
       
  1116  * 
       
  1117  ***************************************************************************************/
       
  1118 TDynamicsCallInfo CDynamicsCommand::ParseMobileNodeAgentListOutput( string aOutput, int aListSize, 
       
  1119 								    TMobileNodeForeignAgentInfo *aForeignAgentList, int *aListCount )
       
  1120 {
       
  1121   TDynamicsCallInfo rv;
       
  1122   const char *cline;
       
  1123   int match, priority, in_use_flag, err;
       
  1124   struct in_addr saddr;
       
  1125   char foreign_address_string[TOKENSIZE], interface_name_string[TOKENSIZE], white_space[TOKENSIZE];
       
  1126 
       
  1127   // check params
       
  1128   assert( aForeignAgentList != NULL );
       
  1129   assert( aListCount != NULL );
       
  1130   memset( &rv, 0, sizeof(rv) );
       
  1131   rv.iResult = DC_SUCCESS;
       
  1132   *aListCount = 0;
       
  1133 
       
  1134   // the first line should be "List of heard mobility agents:\n"
       
  1135   cline = aOutput.c_str();
       
  1136   assert( cline != NULL );
       
  1137   match = strncmp( MOBILE_AGENT_FOREIGN_AGENT_LIST_PREFIX, cline, strlen(MOBILE_AGENT_FOREIGN_AGENT_LIST_PREFIX) );
       
  1138   if( match != 0 ) {
       
  1139       rv.iResult = DC_UNEXPECTED_OUTPUT;
       
  1140       return rv;
       
  1141   }
       
  1142 
       
  1143   // now process each line 
       
  1144   while( 1 ) {
       
  1145     
       
  1146     // move to the next line
       
  1147     cline = strchr( cline, '\n' );
       
  1148     cline++;
       
  1149     
       
  1150     // if are at the end of input then we are done
       
  1151     if( *cline == 0 ) {
       
  1152       break;
       
  1153     }
       
  1154 
       
  1155     // if the list is full then we are done
       
  1156     if( (*aListCount) >= aListSize ) {
       
  1157       break;
       
  1158     }
       
  1159     
       
  1160     // parse the line: IP_ADDR + WHITESPACE + INTERFACENAME + WHITESPACE + prio + 100 + ...
       
  1161     err = sscanf( cline, "%s%[ \t]%s%[ \t]prio%[ \t]%d", foreign_address_string, white_space, interface_name_string, 
       
  1162 		  white_space, white_space, &priority );
       
  1163     if( err != 6 ) {
       
  1164       rv.iResult = DC_UNEXPECTED_OUTPUT;
       
  1165       break;
       
  1166     }
       
  1167 
       
  1168     // check for flags in the line - IN-USE
       
  1169     in_use_flag = strstrbeforedelim( cline, "IN-USE", '\n' );
       
  1170 
       
  1171     // save these values in the list making appropriate conversions
       
  1172     inet_aton( foreign_address_string, &saddr );
       
  1173     aForeignAgentList[(*aListCount)].iForeignAgentAddress = saddr.ADDRESS_INTEGER;
       
  1174     STRNCPY_NULL_TERMINATE( aForeignAgentList[(*aListCount)].iInterfaceName, interface_name_string, MAXINTERFACENAME );
       
  1175     aForeignAgentList[(*aListCount)].iInUse = ((in_use_flag == 0) ? 1 : 0);
       
  1176     aForeignAgentList[(*aListCount)].iPriority = priority;
       
  1177 
       
  1178     // fill in the fields not got here
       
  1179     aForeignAgentList[(*aListCount)].iInterfaceIndex = 0;
       
  1180     aForeignAgentList[(*aListCount)].iLastAdvertisement = 0;
       
  1181     aForeignAgentList[(*aListCount)].iNAI[0] = 0;
       
  1182 
       
  1183     // update the list count
       
  1184     (*aListCount) += 1;
       
  1185   }      
       
  1186     
       
  1187   // done 
       
  1188   return rv;
       
  1189 }
       
  1190 
       
  1191 
       
  1192 /****************************************************************************************
       
  1193  * 
       
  1194  * PRIVATE METHOD: DynamicsCall
       
  1195  * 
       
  1196  ***************************************************************************************/
       
  1197 TDynamicsCallInfo CDynamicsCommand::DynamicsCall( char *aExecutable, char *aCommand, char *aParams, 
       
  1198 						  string *aStandardOutput, string *aStandardError )
       
  1199 {
       
  1200   int command_length, match, errcode;
       
  1201   TDynamicsCallInfo rv;
       
  1202   CAProcess proc;
       
  1203   TCAProcessError perr;
       
  1204   char dynamics_error_string[MAXIMUMERRORSTRINGLENGTH], *ptr, *submatch;
       
  1205 
       
  1206 	// check params
       
  1207 	assert( aExecutable != NULL );
       
  1208 	assert( aCommand != NULL );
       
  1209 	assert( aStandardOutput != NULL );
       
  1210 	assert( aStandardError != NULL );
       
  1211 
       
  1212 	// init the rv
       
  1213 	memset( &rv, 0, sizeof(rv) );
       
  1214 
       
  1215 	// create the command line for this call
       
  1216 	snprintf( iCommandLine, MAXCOMMANDLINE, "%s %s", aExecutable, aCommand );
       
  1217 
       
  1218 	// append the params if set
       
  1219 	if( aParams != NULL ) {
       
  1220 		command_length = strlen( iCommandLine );
       
  1221 		snprintf( &(iCommandLine[command_length]), (MAXCOMMANDLINE - command_length), " %s", aParams );
       
  1222 	}
       
  1223 
       
  1224 	// append the config file if set
       
  1225 	if( iPipePath.length() != 0 ) {
       
  1226 		command_length = strlen( iCommandLine );
       
  1227 		snprintf( &(iCommandLine[command_length]), (MAXCOMMANDLINE - command_length), " -p %s", iPipePath.c_str() );
       
  1228 	}
       
  1229 
       
  1230 	// now run the command line and trap the output
       
  1231 	//	fprintf( stderr, "COMMANDLINE: '%s'\n", iCommandLine );
       
  1232 	perr = proc.Execute( iCommandLine, &errcode, iTimeout, aStandardOutput, aStandardError );
       
  1233 	if( perr != CAE_NONE ) {
       
  1234 		rv.iResult = DC_EXECUTE_FAILED;
       
  1235 		rv.iErrorCode = (int)perr;
       
  1236 		rv.iErrorDetail = errcode;
       
  1237 		return rv;
       
  1238 	}
       
  1239 
       
  1240 	// see if there was a 'csh:' error
       
  1241 	match = strncmp( CSH_FAILED_PREFIX, aStandardError->c_str(), strlen(CSH_FAILED_PREFIX) );
       
  1242 	if( match == 0 ) {
       
  1243 	  submatch = strstr( aStandardError->c_str(), TARGET_NOT_FOUND );
       
  1244 	  rv.iResult = ((submatch == NULL) ? DC_CSH_FAILED: DC_COMMAND_TOOL_NOT_FOUND);
       
  1245 	  rv.iErrorCode = 0;
       
  1246 	  rv.iErrorDetail = 0;
       
  1247 	  if( rv.iResult == DC_CSH_FAILED ) {
       
  1248 	    STRNCPY_NULL_TERMINATE( dynamics_error_string, aStandardError->c_str(), MAXIMUMERRORSTRINGLENGTH );
       
  1249 	    ptr = &(dynamics_error_string[strlen(CSH_FAILED_PREFIX)]);
       
  1250 	    STRNCPY_NULL_TERMINATE( rv.iDynamicsErrorString, ptr, MAXIMUMERRORSTRINGLENGTH );
       
  1251 	  }
       
  1252 	  return rv;
       
  1253 	}
       
  1254 
       
  1255 	// see if there was a 'Call failed: ' error
       
  1256 	match = strncmp( CALL_FAILED_PREFIX, aStandardOutput->c_str(), strlen(CALL_FAILED_PREFIX) );
       
  1257 	if( match == 0 ) {
       
  1258 		rv.iResult = DC_CALL_FAILED;
       
  1259 		rv.iErrorCode = GetCallFailedReason( aStandardOutput->c_str() );
       
  1260 		rv.iErrorDetail = 0;
       
  1261 		if( rv.iErrorCode == DCF_UNKNOWN ) {
       
  1262 		  STRNCPY_NULL_TERMINATE( dynamics_error_string, aStandardOutput->c_str(), MAXIMUMERRORSTRINGLENGTH );
       
  1263 		  ptr = &(dynamics_error_string[strlen(CALL_FAILED_PREFIX)]);
       
  1264 		  STRNCPY_NULL_TERMINATE( rv.iDynamicsErrorString, ptr, MAXIMUMERRORSTRINGLENGTH );
       
  1265 		} else {
       
  1266 		  rv.iDynamicsErrorString[0] = 0;
       
  1267 		}
       
  1268 		return rv;
       
  1269 	}
       
  1270 
       
  1271 	// see if there was an 'Invalid arguments. ' error
       
  1272 	match = strncmp( INVALID_ARGUMENTS_PREFIX, aStandardOutput->c_str(), strlen(INVALID_ARGUMENTS_PREFIX) );
       
  1273 	if( match == 0 ) {
       
  1274 		rv.iResult = DC_INVALID_ARGUMENTS;
       
  1275 		rv.iErrorCode = 0;
       
  1276 		rv.iErrorDetail = 0;
       
  1277 		STRNCPY_NULL_TERMINATE( dynamics_error_string, aStandardOutput->c_str(), MAXIMUMERRORSTRINGLENGTH );
       
  1278 		ptr = &(dynamics_error_string[strlen(INVALID_ARGUMENTS_PREFIX)]);
       
  1279 		STRNCPY_NULL_TERMINATE( rv.iDynamicsErrorString, ptr, strlen(INVALID_ARGUMENTS_PREFIX) );
       
  1280 		return rv;
       
  1281 	}
       
  1282 	
       
  1283 	// otherwise everything looks ok - return the output for the upper layer to translate
       
  1284 	rv.iResult = DC_SUCCESS;
       
  1285 	rv.iErrorCode = 0;
       
  1286 	rv.iErrorDetail = 0;
       
  1287 	(rv.iDynamicsErrorString)[0] = 0;
       
  1288 	return rv;
       
  1289 }
       
  1290 
       
  1291 
       
  1292 /****************************************************************************************
       
  1293  * 
       
  1294  * PRIVATE METHOD: GetCallFailedReason
       
  1295  * 
       
  1296  ***************************************************************************************/
       
  1297 TDynamicsCallFailedReason CDynamicsCommand::GetCallFailedReason( const char *aOutput )
       
  1298 {
       
  1299   int match;
       
  1300   const char *err_string;
       
  1301 
       
  1302   // validate that this is a call failed 
       
  1303   match = strncmp( CALL_FAILED_PREFIX, aOutput, strlen(CALL_FAILED_PREFIX) );
       
  1304   assert( match == 0 );
       
  1305 
       
  1306   // get the error string
       
  1307   err_string = &(aOutput[strlen(CALL_FAILED_PREFIX)]);
       
  1308 
       
  1309   // check for 'function not permitted'
       
  1310   match = strncmp( CALL_FAILED_FUNCTION_NOT_PERMITTED, err_string, strlen(CALL_FAILED_FUNCTION_NOT_PERMITTED) );
       
  1311   if( match == 0 ) {
       
  1312     return DCF_FUNCTION_NOT_PERMITTED;
       
  1313   }
       
  1314 
       
  1315   // check for 'agent unreachable'
       
  1316   match = strncmp( CALL_FAILED_AGENT_UNREACHABLE, err_string, strlen(CALL_FAILED_AGENT_UNREACHABLE) );
       
  1317   if( match == 0 ) {
       
  1318     return DCF_AGENT_UNREACHABLE;
       
  1319   }
       
  1320 
       
  1321   // can't interpret
       
  1322   return DCF_UNKNOWN;
       
  1323 }
       
  1324 
       
  1325 
       
  1326 
       
  1327 /****************************************************************************************
       
  1328  * 
       
  1329  * PRIVATE METHOD: ConvertTunnelStringToInteger
       
  1330  * 
       
  1331  ***************************************************************************************/
       
  1332 int CDynamicsCommand::ConvertTunnelStringToInteger( char *aTunnelMode, int *aValue )
       
  1333 {
       
  1334   int rv = -1, i, match;
       
  1335 
       
  1336   // check params
       
  1337   assert( aTunnelMode != NULL );
       
  1338   assert( aValue != NULL );
       
  1339   *aValue = -1;
       
  1340 
       
  1341   // look for a match
       
  1342   for( i = 0; iTunnelModeString[i] != NULL; i++ ) {
       
  1343     match = strncmp( iTunnelModeString[i], aTunnelMode, strlen(iTunnelModeString[i]) );
       
  1344     if( match == 0 ) {
       
  1345       *aValue = i;
       
  1346       rv = 0;
       
  1347     }
       
  1348   }
       
  1349 
       
  1350   // done
       
  1351   return rv;
       
  1352 }
       
  1353 
       
  1354 
       
  1355 /****************************************************************************************
       
  1356  * 
       
  1357  * PRIVATE METHOD: CheckMatchAsBoolean
       
  1358  * 
       
  1359  ***************************************************************************************/
       
  1360 int CDynamicsCommand::CheckMatchAsBoolean( char *aInput, char *aTrue, int *aValue )
       
  1361 {
       
  1362   int match;
       
  1363 
       
  1364   // check params
       
  1365   assert( aInput != NULL );
       
  1366   assert( aTrue != NULL );
       
  1367   assert( aValue != NULL );
       
  1368 
       
  1369   // check match
       
  1370   match = strcmp( aInput, aTrue );
       
  1371   *aValue = ((match == 0) ? 1 : 0);
       
  1372   return 0;
       
  1373 }
       
  1374 
       
  1375 
       
  1376 /****************************************************************************************
       
  1377  * 
       
  1378  * PRIVATE METHOD: strstrbeforedelim
       
  1379  * 
       
  1380  ***************************************************************************************/
       
  1381 int CDynamicsCommand::strstrbeforedelim( const char *aSearchSpace, const char *aToken, char aDelim )
       
  1382 {
       
  1383   char *next_delim_position, *next_substr_position;
       
  1384  
       
  1385   // check params
       
  1386   assert( aSearchSpace != NULL );
       
  1387   assert( aToken != NULL );
       
  1388   
       
  1389   // look for the substr - if not found then not found
       
  1390   next_substr_position = strstr( aSearchSpace, aToken );
       
  1391   if( next_substr_position == NULL ) {
       
  1392     return -1;
       
  1393   }
       
  1394 
       
  1395   // look for the delim - if not found then the substr was found
       
  1396   next_delim_position = strchr( aSearchSpace, aDelim );
       
  1397   if( next_delim_position == NULL ) {
       
  1398     return 0;
       
  1399   }
       
  1400 
       
  1401   // see which one came first
       
  1402   if( next_substr_position < next_delim_position ) {
       
  1403     return 0;
       
  1404   }
       
  1405   return -1;
       
  1406 }
       
  1407 
       
  1408