datacommsserver/esockserver/test/TS_MultiHoming/TS_MultiHomingSuite.cpp
changeset 0 dfb7c4ff071f
equal deleted inserted replaced
-1:000000000000 0:dfb7c4ff071f
       
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // This defines the CTS_MultiHomingSuite class which is the 
       
    15 // container class for the TS_MultiHomingStep-derived test steps
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22 
       
    23 #include "TS_MultiHomingSuite.h"
       
    24 #include "TS_RConnectionStart.h"
       
    25 #include "TS_RConnectionClose.h"
       
    26 #include "TS_RConnectionStop.h"
       
    27 #include "TS_TestConnection.h"
       
    28 #ifdef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
    29 #include "ts_testincomming.h"
       
    30 #endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
    31 #include "TS_CopyComDbFile.h"
       
    32 #include "TS_ShowConnections.h"
       
    33 #include "TS_ResolveName.h"
       
    34 #include "TS_ResolveAddress.h"
       
    35 #include "TS_GetConnectionInfo.h"
       
    36 #include "TS_CheckLinkLocalSame.h"
       
    37 #include "TS_Delay.h"
       
    38 #include <e32cons.h>
       
    39 #include <in_sock.h>
       
    40 #include <in_iface.h>
       
    41 #include <nifman.h>
       
    42 					  
       
    43 
       
    44 EXPORT_C CTS_MultiHomingSuite* NewTS_MultiHomingSuite( void ) 
       
    45 /** Polymorphic interface, exported ordinal 1.  Called by scheduletest
       
    46  * and used to instantiate the suite
       
    47  * @return A pointer to the created CTS_MultiHomingSuite object
       
    48  */
       
    49     {
       
    50 	CTS_MultiHomingSuite* ts = 0;
       
    51 	TRAPD(err,ts = new (ELeave) CTS_MultiHomingSuite);
       
    52 	if (err == KErrNone)
       
    53 		return ts;
       
    54 	return 0;
       
    55     }
       
    56 
       
    57 CTS_MultiHomingSuite::~CTS_MultiHomingSuite()
       
    58 /** 
       
    59  * Destructor has to clean up any TConnDetails left hanging around
       
    60  * 
       
    61  */
       
    62 	{
       
    63 	delete iScheduler;
       
    64 	}
       
    65 
       
    66 void CTS_MultiHomingSuite::AddTestStepL( CTS_MultiHomingStep* ptrTestStep )
       
    67 /**
       
    68  * Adds a test step to the test suite object, using the base class method
       
    69  * @param ptrTestStep A pointer to the test step to be added
       
    70  * @exception Can leave
       
    71  */
       
    72 	{
       
    73 	ptrTestStep->iOwnerSuite = this; 
       
    74 	CTestSuite::AddTestStepL(ptrTestStep);
       
    75 	}
       
    76 
       
    77 void CTS_MultiHomingSuite::InitialiseL( void )
       
    78 /**
       
    79  * Effective second-phase constructor.  Creates all suite test steps
       
    80  * and associates them with the suite.
       
    81  */
       
    82 	{
       
    83 	// Load the serial drivers
       
    84 	TInt ret = User::LoadPhysicalDevice(PDD_NAME);
       
    85 	if ( KErrNone != ret && KErrAlreadyExists != ret )
       
    86 		{
       
    87 		User::Leave( ret );
       
    88 		}
       
    89 		
       
    90 	ret = User::LoadLogicalDevice(LDD_NAME);
       
    91 	if ( KErrNone != ret && KErrAlreadyExists != ret )
       
    92 		{
       
    93 		User::Leave( ret );
       
    94 		}
       
    95 
       
    96  	// When bootstrapping C32 we have to avoid the PhBkSyncServer being started, since
       
    97  	// it needs a different CommDB
       
    98  	_LIT(KPhbkSyncCMI, "phbsync.cmi");
       
    99     ret = StartC32WithCMISuppressions(KPhbkSyncCMI);
       
   100 	if ( KErrNone != ret && KErrAlreadyExists != ret )
       
   101 		{
       
   102 		User::Leave( ret );
       
   103 		}
       
   104 
       
   105 	//Make the scheduler...
       
   106 	
       
   107 	iScheduler=new(ELeave) CEnhancedScheduler();
       
   108 	CEnhancedScheduler::Install(iScheduler);
       
   109 	
       
   110 
       
   111 	// Add Test steps	
       
   112 	AddTestStepL( new(ELeave) CTS_RConnectionStart );
       
   113 	AddTestStepL( new(ELeave) CTS_RConnectionClose );
       
   114 	AddTestStepL( new(ELeave) CTS_RConnectionStop  );
       
   115 	AddTestStepL( new(ELeave) CTS_TestConnection   );
       
   116 
       
   117 #ifdef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
   118 	AddTestStepL( new(ELeave) CTS_TestIncomming   );
       
   119 #endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
   120 	AddTestStepL( new(ELeave) CTS_ShowConnections  );
       
   121 	AddTestStepL( new(ELeave) CTS_ResolveName );
       
   122 	AddTestStepL( new(ELeave) CTS_ResolveAddress );
       
   123 	AddTestStepL( new(ELeave) CTS_GetConnectionInfo );
       
   124 	AddTestStepL( new(ELeave) CTS_CheckLinkLocalSame );
       
   125 	AddTestStepL( new(ELeave) CTS_CopyComDbFile );
       
   126 	AddTestStepL( new(ELeave) CTS_Delay );
       
   127 	}
       
   128 
       
   129 
       
   130 TPtrC CTS_MultiHomingSuite::GetVersion( void )
       
   131 /**
       
   132  * Give version information back to Schedultest
       
   133  * @return The descriptor of the version
       
   134  */
       
   135 	{
       
   136 	return KTxtVersion();
       
   137 	}
       
   138 
       
   139 
       
   140 TInt CTS_MultiHomingSuite::GetConnIndex(const TDesC& aName)
       
   141 /**
       
   142  * Gets the array index of the name passed in
       
   143  * @param aName Descriptor containing the connection name to match
       
   144  * @return The index, or KErrNotFound
       
   145  */
       
   146 	{
       
   147 	for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++)
       
   148 		{
       
   149 		if (iConnections[i].MatchName(aName))
       
   150 			return i;
       
   151 		}
       
   152 	return KErrNotFound;
       
   153 	}
       
   154 
       
   155 
       
   156 TConnDetails *CTS_MultiHomingSuite::GetNewTConnection( )
       
   157 /**
       
   158  * Retreive 
       
   159  *
       
   160  */
       
   161 	{
       
   162 	for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++)
       
   163 		{
       
   164 		if (iConnections[i].iName.Length() == 0)
       
   165 			return &iConnections[i];
       
   166 		}
       
   167 	return 0;
       
   168 	}
       
   169 
       
   170 TInt CTS_MultiHomingSuite::AddConnection(const TConnDetails& aConn)
       
   171 /**
       
   172  * Appends a connection to the array of connections in the suite
       
   173  * @param aName Reference to the object to pass in
       
   174  * @return System wide error code 
       
   175  */
       
   176 	{
       
   177 	TInt err= KErrNone;			// Check the name doesn't already exist
       
   178 	TInt connIndex = GetConnIndex(aConn.iName);
       
   179 	if(KErrNotFound == connIndex)
       
   180 		{
       
   181 		//err = iConnections.Append(aConn);
       
   182 		}
       
   183 	else
       
   184 		{
       
   185 		err = KErrAlreadyExists;
       
   186 		_LIT(KMultipleConns, "Connection has already been started. Check configuration files.");
       
   187 		LogExtra((TText8*)__FILE__, __LINE__, ESevrInfo, KMultipleConns);
       
   188 		}
       
   189 
       
   190 	return err;
       
   191 	}
       
   192 
       
   193 TConnDetails *CTS_MultiHomingSuite::GetTConnection(const TDesC& aName)
       
   194 /**
       
   195  * Returns the TConnection object for a specific connection
       
   196  * @param aName Name of connection to look up
       
   197  * @return The RConnection object
       
   198  */
       
   199 
       
   200 	{
       
   201 	TInt err= KErrNone;
       
   202 	err = GetConnIndex(aName);
       
   203 	if (err == KErrNotFound)
       
   204 		{
       
   205 		//User::Panic(KTxtSuiteName, err);
       
   206 		return 0;
       
   207 		}
       
   208 	return &iConnections[err];
       
   209 	}
       
   210 	
       
   211 RConnection *CTS_MultiHomingSuite::GetRConnection(const TDesC& aName)
       
   212 /**
       
   213  * Returns the RConnection object for a specific connection
       
   214  * @param aName Name of connection to look up
       
   215  * @return The RConnection object
       
   216  */
       
   217     {
       
   218 	TInt err= KErrNone;
       
   219 	err = GetConnIndex(aName);
       
   220 	if (err == KErrNotFound)
       
   221 		{
       
   222 		//User::Panic(KTxtSuiteName, err);
       
   223 		return 0;
       
   224 		}
       
   225 	return &iConnections[err].iConnection;
       
   226 	}
       
   227 
       
   228 RSocketServ *CTS_MultiHomingSuite::GetRSocketServ(const TDesC& aName)
       
   229 /**
       
   230  * Returns the RSocketServ object for a specific connection
       
   231  * @param aName Name of connection to look up
       
   232  * @return The RSocketServ object
       
   233  */
       
   234 	{
       
   235 	TInt connIndex = -1;
       
   236 
       
   237 	connIndex = GetConnIndex(aName);
       
   238 	if (connIndex < 0)
       
   239 		{
       
   240 		return 0;
       
   241 		}
       
   242 	return &iConnections[connIndex].iSocketServ;
       
   243 	}
       
   244 
       
   245 
       
   246 TInt CTS_MultiHomingSuite::CloseConnection(const TDesC& aName)
       
   247 /** 
       
   248  * Closes a connection and removes it from the array
       
   249  * @param aName The name of the connection to close
       
   250  * @return System wide error code
       
   251  */
       
   252 	{
       
   253 	TInt index= KErrNone;
       
   254 	index= GetConnIndex(aName);
       
   255 	if (index != KErrNotFound)
       
   256 		{
       
   257 		if (iConnections[index].iClients == 0)		// No open sockets, so can close
       
   258 			{
       
   259 			if(iConnections[index].iConnectionType 
       
   260 				!= TConnDetails::implicitConn)
       
   261 				{
       
   262 				iConnections[index].iConnection.Close();
       
   263 				}
       
   264 			else
       
   265 				{
       
   266 				iConnections[index].iSocket.Close();
       
   267 				}
       
   268 
       
   269 			iConnections[index].iSocketServ.Close();
       
   270 			iConnections[index].iName.Zero();
       
   271 			return KErrNone;
       
   272 			}
       
   273 		return KErrInUse;
       
   274 		}
       
   275 	return index;
       
   276 	}
       
   277 
       
   278 
       
   279 TInt CTS_MultiHomingSuite::StopConnection(const TDesC& aName)
       
   280 /** 
       
   281  * Closes a connection and removes it from the array
       
   282  * @param aName The name of the connection to close
       
   283  * @return System wide error code
       
   284  */
       
   285 	{
       
   286 	TInt index= KErrNone;
       
   287 	index= GetConnIndex(aName);
       
   288 	if (index != KErrNotFound)
       
   289 		{
       
   290 		if (iConnections[index].iClients == 0)		// No open sockets, so can close
       
   291 			{
       
   292 			if(iConnections[index].iConnectionType 
       
   293 				!= TConnDetails::implicitConn)
       
   294 				{
       
   295 				iConnections[index].iConnection.Stop();	//< Any connections present killed
       
   296 				}
       
   297 			else
       
   298 				{
       
   299 				iConnections[index].iSocket.Close();
       
   300 				}
       
   301 
       
   302 			iConnections[index].iSocketServ.Close();
       
   303 			iConnections[index].iName.Zero();
       
   304 			return KErrNone;
       
   305 			}
       
   306 		return KErrInUse;
       
   307 		}
       
   308 	return index;
       
   309 	}
       
   310 
       
   311 
       
   312 inline void RemoveScopeFromAddress(TName& address)
       
   313 	{
       
   314 	TChar percent('%');
       
   315 	TInt percentIndex = address.Locate(percent);
       
   316 	
       
   317 	if( percentIndex >= 0 )
       
   318 		{
       
   319 		address.SetLength(percentIndex);
       
   320 		}
       
   321 	}
       
   322 
       
   323 TInt CTS_MultiHomingSuite::DisplayConnectionDetailsL()
       
   324 /**
       
   325  * Displays the IP interfaces that are currently in the system
       
   326  * @return number of non loopback interfaces
       
   327  */
       
   328 	{
       
   329 	TInt err = KErrNone;
       
   330 	for (TInt i=0; i < CTS_MultiHomingSuite::MAX_CONNECTIONS; i++)
       
   331 		{
       
   332 		if(iConnections[i].iName.Length() == 0)
       
   333 			{
       
   334 			continue;
       
   335 			}
       
   336 		_LIT (KConnLogString, "Name [%S], RConnection[%x], RSocketServ[%x]");
       
   337 		Log(KConnLogString, &iConnections[i].iName,
       
   338 							&iConnections[i].iConnection,
       
   339 							&iConnections[i].iSocketServ);
       
   340 	
       
   341 		}
       
   342 
       
   343 	TAutoClose<RSocketServ> ss;
       
   344 	err = ss.iObj.Connect();
       
   345 	ss.PushL();
       
   346 
       
   347 	TAutoClose<RSocket> sock;
       
   348 	err = sock.iObj.Open(ss.iObj, _L("udp"));
       
   349 
       
   350 	sock.PushL();
       
   351 
       
   352 	User::LeaveIfError(sock.iObj.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
       
   353 
       
   354 	TProtocolDesc in;
       
   355 	User::LeaveIfError(sock.iObj.Info(in));
       
   356 	//LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("EPOC32 IP Stack Version %d.%d.%d ---- INTERFACE START"), in.iVersion.iMajor, in.iVersion.iMinor, in.iVersion.iBuild);
       
   357 
       
   358 
       
   359 	TPckgBuf<TSoInetInterfaceInfo> info;
       
   360 	
       
   361 	err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
       
   362 	// The first interface is always empty
       
   363 	err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
       
   364 	TInt numberOfInterfaces = 0;
       
   365 	while(err == KErrNone)
       
   366 		{
       
   367 		// Skip loopback interfaces
       
   368 		if(info().iFeatures & KIfIsLoopback || info().iState != EIfUp) 
       
   369 			{
       
   370 			err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
       
   371 			continue;
       
   372 			}
       
   373 
       
   374 		
       
   375 		TBuf <MAX_LOG_LINE_LENGTH> LineBuf;
       
   376 		
       
   377 
       
   378 		LineBuf.AppendFormat(_L("%S: Tag: \"%S\" is ")
       
   379 					,&info().iName
       
   380 					,&info().iTag);
       
   381 
       
   382 		LineBuf.Append(info().iState == EIfPending ? _L("PENDING") :
       
   383 					   info().iState == EIfUp      ? _L("UP")      :
       
   384 					   info().iState == EIfDown    ? _L("DOWN")    :
       
   385 					   info().iState == EIfBusy    ? _L("BUSY")    :
       
   386 					   _L("UNDEFINED_STATE"));
       
   387 		LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf);
       
   388 
       
   389 		LineBuf.Zero();
       
   390 		LineBuf.AppendFormat(_L("%S: "), &info().iName);
       
   391 
       
   392 		LineBuf.AppendFormat(_L("Mtu: %d Speed: %d "), info().iMtu, info().iSpeedMetric);
       
   393 		LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf);
       
   394 
       
   395 		LineBuf.Zero();
       
   396 		LineBuf.AppendFormat(_L("%S: "), &info().iName);
       
   397 
       
   398 
       
   399 		TName address;
       
   400 		info().iAddress.Output(address);
       
   401 		LineBuf.Append(_L("Address "));
       
   402 		//RemoveScopeFromAddress(address);
       
   403 		LineBuf.Append(address);		
       
   404 		TName netmask;
       
   405 		info().iNetMask.OutputWithScope(netmask);
       
   406 		LineBuf.Append(_L("/"));
       
   407 		LineBuf.Append(netmask);
       
   408 		info().iAddress.IsLinkLocal() ? LineBuf.Append(_L("   is Link local")) :
       
   409 		info().iAddress.IsSiteLocal() ? LineBuf.Append(_L("   is Site local")) :
       
   410 		LineBuf.Append(_L("     is Global"));
       
   411 
       
   412 
       
   413 		LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf);
       
   414 		LineBuf.Zero();
       
   415 		LineBuf.AppendFormat(_L("%S: "), &info().iName);
       
   416 
       
   417 
       
   418 		info().iBrdAddr.Output(address);
       
   419 		//RemoveScopeFromAddress(address);
       
   420 		TChar colon(':');
       
   421 		// Assume single IPv4 addres per interface
       
   422 		if(address.Locate(colon) < 0)
       
   423 			{
       
   424 			numberOfInterfaces++;
       
   425 			}
       
   426 		// 2 == :: ie zeros
       
   427 		if(address.Length() > 3)
       
   428 			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Broadcast address %S"), &info().iName, &address);
       
   429 		info().iDefGate.Output(address);
       
   430 		//RemoveScopeFromAddress(address);
       
   431 		if(address.Length() > 3)
       
   432 			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Default gateway %S"), &info().iName, &address);
       
   433 		info().iNameSer1.Output(address);
       
   434 		//RemoveScopeFromAddress(address);
       
   435 		if(address.Length() > 3)
       
   436 			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Primary DNS %S"), &info().iName, &address);
       
   437 		info().iNameSer2.Output(address);
       
   438 		//RemoveScopeFromAddress(address);
       
   439 		if(address.Length() > 3)
       
   440 			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%S: Secondary DNS %S"), &info().iName, &address);
       
   441 
       
   442 	
       
   443 
       
   444 		if(info().iFeatures & KIfIsLoopback) 
       
   445 			{
       
   446 			LineBuf.Append(_L(" LOOPBACK"));
       
   447 			}
       
   448 		if(info().iFeatures & KIfIsDialup)
       
   449 			{
       
   450 			LineBuf.Append(_L(" DIALUP"));
       
   451 			}
       
   452 		if(info().iFeatures & KIfIsPointToPoint)
       
   453 			{
       
   454 			LineBuf.Append(_L(" POINTTOPOINT"));
       
   455 			}
       
   456 		if(info().iFeatures & KIfCanBroadcast)
       
   457 			{
       
   458 			LineBuf.Append(_L(" BROADCAST"));
       
   459 			}
       
   460 		
       
   461 		if(info().iFeatures & KIfCanMulticast)
       
   462 			{
       
   463 			LineBuf.Append(_L(" MULTICASTCAST"));
       
   464 			}
       
   465 		if(info().iFeatures & KIfCanSetMTU)
       
   466 			{
       
   467 			LineBuf.Append(_L(" SETMTU"));   
       
   468 			}
       
   469 		if(info().iFeatures & KIfCanSetHardwareAddr)
       
   470 			{
       
   471 			LineBuf.Append(_L(" CANSETHWADDR"));
       
   472 			}
       
   473 
       
   474 		LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, LineBuf);
       
   475 		LineBuf.Zero();
       
   476 
       
   477 
       
   478 		if(info().iFeatures & KIfHasHardwareAddr)
       
   479 			{
       
   480 			LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L(" Hardware address "));		
       
   481 			TUint j;
       
   482 			for(j=sizeof(SSockAddr) ; j<sizeof(SSockAddr)+6 ; ++j)
       
   483 				{
       
   484 				if(j<(TUint)info().iHwAddr.Length())
       
   485 					LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("%02X"), info().iHwAddr[j]);
       
   486 				else
       
   487 					LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("??"));
       
   488 				if(j<sizeof(SSockAddr)+5)
       
   489 				   LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("-"));
       
   490 				else
       
   491 					LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L(""));
       
   492 				}
       
   493 			}
       
   494 			err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
       
   495 			
       
   496 		}
       
   497 		
       
   498 	sock.Pop();
       
   499 	ss.Pop();
       
   500 	
       
   501 //	LogExtra(((TText8*)(__FILE__)), (__LINE__), ESevrErr, _L("EPOC32 IP Stack Version %d.%d.%d ---- INTERFACE LIST END"), in.iVersion.iMajor, in.iVersion.iMinor, in.iVersion.iBuild);
       
   502 
       
   503 	return numberOfInterfaces;
       
   504 	}
       
   505 
       
   506 	
       
   507 /**
       
   508  * Compares first two non-loopback link-local addresses
       
   509  * @return TRUE if equal else FALSE
       
   510  */
       
   511 	TBool CTS_MultiHomingSuite::CompareLinkLocalAddressesL()
       
   512 	{
       
   513 		
       
   514 		TName  addresses[2];
       
   515 		TAutoClose<RSocketServ> ss;
       
   516 		TInt err = ss.iObj.Connect();
       
   517 		ss.PushL();
       
   518 		TAutoClose<RSocket> sock;
       
   519 		err = sock.iObj.Open(ss.iObj, _L("udp"));
       
   520 		sock.PushL();
       
   521 
       
   522 		User::LeaveIfError(sock.iObj.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
       
   523 		
       
   524 		TPckgBuf<TSoInetInterfaceInfo> info;
       
   525 		err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
       
   526 		// The first interface is always empty
       
   527 		err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
       
   528 		
       
   529 		TInt i = 0;		
       
   530 		while((i < 2) && (err== KErrNone))
       
   531 			{
       
   532 			// Skip loopback interfaces
       
   533 			if(info().iFeatures & KIfIsLoopback) 
       
   534 				{
       
   535 				err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
       
   536 				continue;
       
   537 				}		
       
   538 							
       
   539 			if (info().iAddress.IsLinkLocal())
       
   540 				{
       
   541 				//TName address;
       
   542 				//addresses[i].FillZ();				
       
   543 				info().iAddress.Output(addresses[i]);						
       
   544 				RemoveScopeFromAddress(addresses[i]);
       
   545 				i++;
       
   546 				}
       
   547 
       
   548 			err = sock.iObj.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info);
       
   549 			}
       
   550 
       
   551 		sock.Pop();
       
   552 		ss.Pop();
       
   553 		
       
   554 		if ((i == 2) && (addresses[0].Compare(addresses[1]) == 0))					
       
   555 			return TRUE;
       
   556 		return FALSE;
       
   557 	}
       
   558