testexecmgmt/ucc/Source/AliasLibrary/CInterfaceAlias.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 * Switches
       
    16 * System Includes
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 #include <stdio.h>
       
    23 #include <stdlib.h>
       
    24 #include <unistd.h>
       
    25 #include <fcntl.h>
       
    26 #include <errno.h>
       
    27 #include <sys/types.h>
       
    28 #include <sys/wait.h>
       
    29 #include <signal.h>
       
    30 #include <sys/socket.h>
       
    31 #include <sys/ioctl.h>
       
    32 #include <net/if.h>
       
    33 #include <assert.h>
       
    34 #include <string.h>
       
    35 #include <netinet/in.h>
       
    36 #include <arpa/inet.h>
       
    37 #include <ctype.h>
       
    38 
       
    39 /*******************************************************************************
       
    40  *
       
    41  * Local Includes
       
    42  *
       
    43  ******************************************************************************/
       
    44 #include "CInterfaceAlias.h"
       
    45 
       
    46 /*******************************************************************************
       
    47  *
       
    48  * Macro Functions
       
    49  *
       
    50  ******************************************************************************/
       
    51 
       
    52 /*******************************************************************************
       
    53  *
       
    54  * Definitions
       
    55  *
       
    56  ******************************************************************************/
       
    57 #define MAXALIASNAME                  64
       
    58 #define MAXALIASCOUNT                 1024
       
    59 #define MAXINTERFACECOUNT             1024
       
    60 #define ETHERNET_INTERFACE_PREFIX     "eth"
       
    61 
       
    62 /*******************************************************************************
       
    63  *
       
    64  * IMPLEMENTATION: CInterfaceAlias
       
    65  *
       
    66  ******************************************************************************/
       
    67 
       
    68 /*******************************************************************************
       
    69  *
       
    70  * PUBLIC: CInterfaceAlias
       
    71  *
       
    72  ******************************************************************************/
       
    73 CInterfaceAlias::CInterfaceAlias()
       
    74 {
       
    75   iState = IAS_INIT;
       
    76   iBaseInterfaceIndex = 0;
       
    77   iAliasIndex = 0;
       
    78 }
       
    79 
       
    80 CInterfaceAlias::~CInterfaceAlias()
       
    81 {
       
    82   assert( iState != IAS_UP );
       
    83 }
       
    84 
       
    85 
       
    86 /*******************************************************************************
       
    87  *
       
    88  * PUBLIC: CreateNewInterfaceAlias
       
    89  *
       
    90  ******************************************************************************/
       
    91 TInterfaceAliasError CInterfaceAlias::CreateNewInterfaceAlias( int aBaseInterfaceIndex, int aNetMask, int aHostAddress, int *aAliasIndex, int *aErrorCode )
       
    92 {
       
    93   int alias_index;
       
    94   char alias_name_temp[MAXALIASNAME];
       
    95   int sockfd;
       
    96   int err;
       
    97   struct sockaddr_in base_interface_addr;
       
    98   struct ifreq ifr;
       
    99   struct sockaddr_in *saddr;
       
   100   TInterfaceAliasError rv;
       
   101 
       
   102   // check the state
       
   103   if( iState != IAS_INIT ) {
       
   104     return IE_INVALID_STATE;
       
   105   }
       
   106 
       
   107   // check the params
       
   108   assert( aAliasIndex != NULL );
       
   109   assert( aErrorCode != NULL );
       
   110   *aErrorCode = 0;
       
   111   *aAliasIndex = -1;
       
   112   if( aBaseInterfaceIndex < 0 ) {
       
   113     return IE_INVALID_PARAM;
       
   114   }
       
   115 
       
   116   // get a free alias index
       
   117   rv = GetFreeAliasIndex( aBaseInterfaceIndex, &alias_index, aErrorCode );
       
   118   if( rv != IE_NONE ) {
       
   119     return rv;
       
   120   }
       
   121 
       
   122   // get the address of the base interface
       
   123   rv = GetBaseInterfaceAddress( aBaseInterfaceIndex, &base_interface_addr, aErrorCode );
       
   124   if( rv != IE_NONE ) {
       
   125     return rv;
       
   126   }
       
   127 
       
   128   // now strip off the host part and replace with the passed host address
       
   129   base_interface_addr.sin_addr.s_addr = ChangeHostAddress( base_interface_addr.sin_addr.s_addr, aNetMask, aHostAddress ); 
       
   130 
       
   131   // setup the interface name
       
   132   sprintf( alias_name_temp, "eth%d:%d", aBaseInterfaceIndex, alias_index );
       
   133   assert( (strlen(alias_name_temp) + 1) < IFNAMSIZ );
       
   134 
       
   135   // create a socket to make ioctl calls on
       
   136   sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
       
   137   if( sockfd <= 0 ) {
       
   138     *aErrorCode = errno;
       
   139     return IE_SOCKET_FAILED;
       
   140   }
       
   141 
       
   142   // setup the request
       
   143   memcpy( ifr.ifr_name, alias_name_temp, strlen(alias_name_temp) + 1 );
       
   144   saddr = (struct sockaddr_in*)(&(ifr.ifr_addr));
       
   145   saddr->sin_family = AF_INET;
       
   146   saddr->sin_port = 0;
       
   147   saddr->sin_addr = base_interface_addr.sin_addr;
       
   148 
       
   149   // make the ioctl call
       
   150   err = ioctl( sockfd, SIOCSIFADDR, &ifr );
       
   151   close( sockfd );
       
   152   if( err == -1 ) {
       
   153     *aErrorCode = errno;
       
   154     return IE_IOCTL_FAILED;
       
   155   }
       
   156 
       
   157   // update the state vars
       
   158   iState = IAS_UP;
       
   159   iBaseInterfaceIndex = aBaseInterfaceIndex;
       
   160   *aAliasIndex = iAliasIndex = alias_index;
       
   161   iInterfaceName = alias_name_temp;
       
   162   iInterfaceAddress = inet_ntoa( base_interface_addr.sin_addr );
       
   163 
       
   164   // done
       
   165   return IE_NONE;
       
   166 }
       
   167 
       
   168 
       
   169 /*******************************************************************************
       
   170  *
       
   171  * PUBLIC:  DestroyInterfaceAlias
       
   172  *
       
   173  ******************************************************************************/
       
   174 TInterfaceAliasError CInterfaceAlias::DestroyInterfaceAlias( int *aErrorCode )
       
   175 {
       
   176   int sockfd;
       
   177   int err;
       
   178   struct ifreq ifr;
       
   179   char ifn[64];
       
   180 
       
   181   // check state
       
   182   if( iState != IAS_UP ) {
       
   183     return IE_INVALID_STATE;
       
   184   }
       
   185 
       
   186   // check params
       
   187   assert( aErrorCode != NULL );
       
   188   *aErrorCode = 0;
       
   189 
       
   190   // create a socket to make ioctl calls on
       
   191   sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
       
   192   assert( sockfd >= 0 );
       
   193   
       
   194   // setup the request record
       
   195   sprintf( ifn, "eth%d:%d", iBaseInterfaceIndex, iAliasIndex );
       
   196   memcpy( ifr.ifr_name, ifn, strlen(ifn) + 1 );
       
   197   ifr.ifr_flags = 0;
       
   198   
       
   199   // get the current flags - this is very important since most flags actually go straight through to
       
   200   // base interface - so we need to keep this and just clear the IFF_UP flag which is local to the alias
       
   201   err = ioctl( sockfd, SIOCGIFFLAGS, &ifr );
       
   202   if( err == -1 ) {
       
   203     iState = IAS_DOWN;
       
   204     *aErrorCode = errno;
       
   205     close( sockfd );
       
   206     return IE_IOCTL_FAILED;
       
   207   }
       
   208 
       
   209   // mask out the IFF_UP flag
       
   210   ifr.ifr_flags &= ~IFF_UP; 
       
   211 
       
   212   // make the ioctl calls 
       
   213   err = ioctl( sockfd, SIOCSIFFLAGS, &ifr );
       
   214   close( sockfd );
       
   215   if( err == -1 ) {
       
   216     iState = IAS_DOWN;
       
   217     *aErrorCode = errno;
       
   218     return IE_IOCTL_FAILED;
       
   219   }
       
   220   
       
   221   // otherwise done
       
   222   iState = IAS_DOWN;
       
   223   return IE_NONE;
       
   224 }
       
   225 
       
   226 
       
   227 
       
   228 /*******************************************************************************
       
   229  *
       
   230  * PUBLIC:  GetInterfaceIndex
       
   231  *
       
   232  ******************************************************************************/
       
   233 TInterfaceAliasError CInterfaceAlias::GetInterfaceIndex( int *aBaseInterfaceIndex, int *aAliasIndex )
       
   234 {
       
   235   // check params
       
   236   assert( aBaseInterfaceIndex != NULL );
       
   237   assert( aAliasIndex != NULL );
       
   238 
       
   239   // check state
       
   240   if( iState == IAS_INIT ) {
       
   241     return IE_INVALID_STATE;
       
   242   }
       
   243 
       
   244   // return info
       
   245   *aBaseInterfaceIndex = iBaseInterfaceIndex;
       
   246   *aAliasIndex = iAliasIndex;
       
   247   return IE_NONE;
       
   248 }
       
   249 
       
   250  
       
   251 /*******************************************************************************
       
   252  *
       
   253  * PUBLIC:  GetInterfaceName
       
   254  *
       
   255  ******************************************************************************/
       
   256 TInterfaceAliasError CInterfaceAlias::GetInterfaceName( string *aInterfaceName )
       
   257 {
       
   258   assert( aInterfaceName != NULL );
       
   259   if( iState == IAS_INIT ) {
       
   260     return IE_INVALID_STATE;
       
   261   }
       
   262   *aInterfaceName = iInterfaceName;
       
   263   return IE_NONE;
       
   264 }
       
   265 
       
   266 
       
   267 /*******************************************************************************
       
   268  *
       
   269  * PUBLIC:  GetInterfaceAddress
       
   270  *
       
   271  ******************************************************************************/
       
   272 TInterfaceAliasError CInterfaceAlias::GetInterfaceAddress( string *aInterfaceAddress )
       
   273 {
       
   274   assert( aInterfaceAddress != NULL );
       
   275   if( iState == IAS_INIT ) {
       
   276     return IE_INVALID_STATE;
       
   277   }
       
   278   *aInterfaceAddress = iInterfaceAddress;
       
   279   return IE_NONE;
       
   280 }
       
   281 
       
   282 
       
   283 /*******************************************************************************
       
   284  *
       
   285  * PRIVATE: ParseInterfaceName
       
   286  *
       
   287  ******************************************************************************/
       
   288 int CInterfaceAlias::ParseInterfaceName( char *aInterfaceName, int *aBaseIndex, int *aAliasIndex )
       
   289 {
       
   290   int rv;
       
   291  
       
   292   // check params
       
   293   assert( aInterfaceName != NULL );
       
   294   assert( aBaseIndex != NULL );
       
   295   assert( aAliasIndex != NULL );
       
   296 
       
   297   // init params
       
   298   *aBaseIndex = *aAliasIndex = -1;
       
   299 
       
   300   // do the scanf
       
   301   rv = sscanf( aInterfaceName, "eth%d:%d", aBaseIndex, aAliasIndex );
       
   302 
       
   303   // return valid if at least a base index was read
       
   304   if( rv >= 1 ) {
       
   305     return 1;
       
   306   }
       
   307   return 0;
       
   308 }
       
   309 
       
   310 
       
   311 /*******************************************************************************
       
   312  *
       
   313  * PRIVATE: GetInterfaceList
       
   314  *
       
   315  ******************************************************************************/
       
   316 TInterfaceAliasError CInterfaceAlias::GetInterfaceList( char *aInterfaceBuffer, int aInputBufferLength, int *aOutputBufferLength, int *aErrorCode )
       
   317 {
       
   318   int sockfd;
       
   319   int err;
       
   320   struct ifconf ifc;
       
   321     
       
   322   // check params
       
   323   assert( aInterfaceBuffer != NULL );
       
   324   assert( aOutputBufferLength != NULL );
       
   325   assert( aErrorCode != NULL );
       
   326 
       
   327   // set the params
       
   328   *aOutputBufferLength = *aErrorCode = 0;
       
   329   
       
   330   // create a socket to make ioctl calls on
       
   331   sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
       
   332   if( sockfd <= 0 ) {
       
   333     *aErrorCode = errno;
       
   334     return IE_SOCKET_FAILED;
       
   335   }
       
   336 
       
   337   // do the ioctl() call to retrieve all the interfaces
       
   338   ifc.ifc_len = aInputBufferLength;
       
   339   ifc.ifc_buf = aInterfaceBuffer;
       
   340   err = ioctl( sockfd, SIOCGIFCONF, &ifc );
       
   341   close( sockfd );
       
   342   if( err == -1 ) {
       
   343     *aErrorCode = errno;
       
   344     return IE_IOCTL_FAILED;
       
   345   }
       
   346 
       
   347   // call was successful, set the output buffer length
       
   348   *aOutputBufferLength = ifc.ifc_len;
       
   349 
       
   350   // done
       
   351   return IE_NONE;
       
   352 }
       
   353 
       
   354 
       
   355 /*******************************************************************************
       
   356  *
       
   357  * PRIVATE: GetFreeAliasIndex
       
   358  *
       
   359  ******************************************************************************/ 
       
   360 TInterfaceAliasError CInterfaceAlias::GetFreeAliasIndex( int aBaseInterfaceIndex, int *aAliasIndex, int *aErrorCode )
       
   361 {
       
   362   TInterfaceAliasError rv;
       
   363   struct ifreq ifr[MAXINTERFACECOUNT];  
       
   364   char alias_status[MAXALIASCOUNT];
       
   365   int is_valid, base_index, alias_index, interface_count, i;
       
   366   int base_index_found = 0;
       
   367   int current_alias_count = 0;
       
   368 
       
   369   // check and set params
       
   370   assert( aAliasIndex != NULL );
       
   371   assert( aErrorCode != NULL );
       
   372   *aAliasIndex = 0;
       
   373   *aErrorCode = 0;
       
   374   
       
   375   // clear the arrays
       
   376   memset( alias_status, 0, sizeof(alias_status) );
       
   377 
       
   378   // get the interface list
       
   379   rv = GetInterfaceList( (char*)ifr, sizeof(ifr), &interface_count, aErrorCode );
       
   380   if( rv != IE_NONE ) {
       
   381     return rv;
       
   382   }
       
   383   interface_count = interface_count / sizeof(struct ifreq);
       
   384 
       
   385   // for each interface entry...
       
   386   for( i = 0; i < interface_count; i++ ) {
       
   387     
       
   388     // parse the name of the interface
       
   389     is_valid = ParseInterfaceName( (ifr[i]).ifr_name, &base_index, &alias_index );
       
   390 
       
   391     // process the interface
       
   392     if( (is_valid) && (base_index == aBaseInterfaceIndex) ) {
       
   393       base_index_found = 1;
       
   394       if( alias_index >= 0 ) {
       
   395 	assert( alias_index < MAXALIASCOUNT );
       
   396 	alias_status[alias_index] = 1;
       
   397 	current_alias_count++;
       
   398       }
       
   399     }
       
   400   }
       
   401   
       
   402   // see if there are any free aliases
       
   403   if( current_alias_count == MAXALIASCOUNT ) {
       
   404     return IE_NO_FREE_ALIAS;
       
   405   }
       
   406 
       
   407   // otherwise return the first free alias
       
   408   for( i = 0; i < MAXALIASCOUNT; i++ ) {
       
   409     if( alias_status[i] == 0 )
       
   410       break;
       
   411   }
       
   412   assert( i < MAXALIASCOUNT );
       
   413   
       
   414   // done
       
   415   *aAliasIndex = i;
       
   416   return IE_NONE;
       
   417 }
       
   418 
       
   419 
       
   420 /*******************************************************************************
       
   421  *
       
   422  * PRIVATE: GetBaseInterfaceAddress
       
   423  *
       
   424  ******************************************************************************/ 
       
   425 TInterfaceAliasError CInterfaceAlias::GetBaseInterfaceAddress( int aBaseInterfaceIndex, struct sockaddr_in *aInterfaceAddress, int *aErrorCode )
       
   426 {
       
   427   int sockfd, err;
       
   428   struct ifreq ifr;
       
   429 
       
   430   // check args
       
   431   assert( aInterfaceAddress != NULL );
       
   432   assert( aErrorCode != NULL );
       
   433   *aErrorCode = 0;
       
   434 
       
   435   // create the interface name
       
   436   memset( &ifr, 0, sizeof(ifr) );
       
   437   snprintf( ifr.ifr_name, IFNAMSIZ, "eth%d", aBaseInterfaceIndex );
       
   438   
       
   439   // create a socket to make the ioctl calls on
       
   440   sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
       
   441   if( sockfd <= 0 ) {
       
   442     *aErrorCode = errno;
       
   443     return IE_SOCKET_FAILED;
       
   444   }
       
   445 
       
   446   // make the ioctl call
       
   447   err = ioctl( sockfd, SIOCGIFADDR, &ifr );
       
   448   close( sockfd );
       
   449   if( err == -1 ) {
       
   450     *aErrorCode = errno;
       
   451     return IE_IOCTL_FAILED;
       
   452   }
       
   453     
       
   454   // save the address
       
   455   *aInterfaceAddress = *((struct sockaddr_in*)(&ifr.ifr_addr));
       
   456   
       
   457   // done
       
   458   return IE_NONE;
       
   459 }
       
   460 
       
   461 
       
   462 /*******************************************************************************
       
   463  *
       
   464  * PRIVATE: ChangeHostAddress
       
   465  *
       
   466  ******************************************************************************/ 
       
   467 int CInterfaceAlias::ChangeHostAddress( int aBaseAddress, int aNetMask, int aHostAddress )
       
   468 {
       
   469   int hostmask = 0;
       
   470   int netmask = 0;
       
   471   int rv;
       
   472 
       
   473   // create masks for the netpart and the hostpart
       
   474   netmask = NetmaskFromBitcount( aNetMask );
       
   475   hostmask = ~netmask;
       
   476 
       
   477   // now create the address
       
   478   rv = ntohl( aBaseAddress );
       
   479   rv &= netmask;
       
   480   rv |= (aHostAddress & hostmask);
       
   481   rv = htonl( rv );
       
   482   return rv;
       
   483 }
       
   484 
       
   485 
       
   486 /*******************************************************************************
       
   487  *
       
   488  * PRIVATE: NetmaskFromBitcount
       
   489  *
       
   490  ******************************************************************************/ 
       
   491 int CInterfaceAlias::NetmaskFromBitcount( int aBitCount )
       
   492 {
       
   493   int i, netmask = 0;
       
   494   for( netmask = 0, i = 0; i < aBitCount; i++ ) {
       
   495     netmask |= 1<<(31-i);
       
   496   }
       
   497   return netmask;
       
   498 }