networkingutils/ipadministrationtool/src/engine.cpp
branchRCL_3
changeset 10 4ca382093dae
parent 5 6beaa9cf4752
child 11 493058e57c8c
equal deleted inserted replaced
5:6beaa9cf4752 10:4ca382093dae
     1 // Copyright (c) 2004-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 // engine.cpp - IP administration tool engine
       
    15 //
       
    16 
       
    17 #include <eikenv.h>
       
    18 #include "ipadm.h"
       
    19 #include "engine.h"
       
    20 
       
    21 #include "uniload.h"
       
    22 
       
    23 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    24 #include <in_sock_internal.h>
       
    25 #endif
       
    26 
       
    27 #ifndef __SECURE_DATA__
       
    28 #define DEFAULT_ROUTES_FILE	_L("C:\\Data\\IpAdm\\route.ini")
       
    29 #else
       
    30 #define DEFAULT_ROUTES_FILE	_L("route.ini")
       
    31 #endif
       
    32 
       
    33 LOCAL_C void AppendInterfaceStatus(TDes& buf, const TInt aStatus)
       
    34 	{
       
    35 	switch (aStatus)
       
    36 		{
       
    37 		case EIfPending:	buf.Append(_L("PEND ")); break;
       
    38 		case EIfUp:			break;
       
    39 		case EIfBusy:		buf.Append(_L("BUSY ")); break;
       
    40 		case EIfDown:		buf.Append(_L("DOWN ")); break;
       
    41 		default:			buf.Append(_L("???? ")); break;
       
    42 		}
       
    43 	}
       
    44 
       
    45 LOCAL_C void AppendInterfaceName(TDes& buf, const TName& aName)
       
    46 	{
       
    47 	if (aName.Length() > 0)
       
    48 		{
       
    49 		buf.Append(aName);
       
    50 		}
       
    51 	else
       
    52 		{
       
    53 		buf.Append(_L("default"));
       
    54 		}
       
    55 	}
       
    56 
       
    57 LOCAL_C void AppendRouteType(TDes& buf, const TInt aType)
       
    58 	{
       
    59 	switch (aType)
       
    60 		{
       
    61 		case ERtNormal:		buf.Append(_L(" ")); break;
       
    62 		case ERtUser:		buf.Append(_L("u ")); break;
       
    63 		case ERtIcmpAdd:	buf.Append(_L("- ")); break; // for IPv6, this is ND entry
       
    64 		case ERtIcmpDel:	buf.Append(_L("d ")); break;
       
    65 		default:			buf.Append(_L("? ")); break;
       
    66 		}
       
    67 	}
       
    68 
       
    69 LOCAL_C void AppendRouteState(TDes& buf, const TInt aState)
       
    70 	{
       
    71 	switch (aState)
       
    72 		{
       
    73 		case ERtNone:		buf.Append(_L("NONE ")); break;
       
    74 		case ERtPending:	buf.Append(_L("PEND ")); break;
       
    75 		case ERtBusy:		buf.Append(_L("BUSY ")); break;
       
    76 		case ERtReady:		break;
       
    77 		case ERtDown:		buf.Append(_L("DOWN ")); break;
       
    78 		default:			buf.Append(_L("???? ")); break;
       
    79 		}
       
    80 	}
       
    81 
       
    82 //
       
    83 //
       
    84 // Just count the number of rightmost zeroes in an IPv6 address
       
    85 // and return (128 - count).
       
    86 //
       
    87 LOCAL_C TInt MaskLength(const TIp6Addr &aAddr)
       
    88 	{
       
    89 	TInt count = 0;
       
    90 	for (TInt i = sizeof(aAddr.u.iAddr8) / sizeof(aAddr.u.iAddr8[0]); --i >= 0; )
       
    91 		{
       
    92 		if (aAddr.u.iAddr8[i])
       
    93 			{
       
    94 			TUint8 nonZeroByte = aAddr.u.iAddr8[i];
       
    95 			while ((nonZeroByte & 1) == 0)
       
    96 				{
       
    97 				count += 1;
       
    98 				nonZeroByte >>= 1;
       
    99 				}
       
   100 			break;
       
   101 			}
       
   102 		count += 8;
       
   103 		}
       
   104 	return 128-count;
       
   105 	}
       
   106 
       
   107 
       
   108 LOCAL_C TInt MaskLength(TUint32 aAddr)
       
   109 	{
       
   110 	TInt count = 0;
       
   111 	// obviously, this is "brute force" counting
       
   112 	while (aAddr & 0x80000000)
       
   113 		{
       
   114 		count++;
       
   115 		aAddr <<= 1;
       
   116 		}
       
   117 	return count;
       
   118 	}
       
   119 
       
   120 
       
   121 // TRawAddr
       
   122 // *********
       
   123 // Lightweight internal help class for handling the link layer addresses
       
   124 //
       
   125 class TRawAddr : public TSockAddr
       
   126 	{
       
   127 public:
       
   128 
       
   129 	void Output(TDes& aBuf) const
       
   130 		{
       
   131 		TUint8* p = (TUint8*)UserPtr();
       
   132 		TInt len = ((TSockAddr *)this)->GetUserLen();	//lint !e1773 // it's a kludge but works anyway
       
   133 
       
   134 		aBuf.SetLength(0);
       
   135 		if (len == 0)
       
   136 			return;
       
   137 		if (aBuf.MaxLength() < len * 4)
       
   138 			{
       
   139 			aBuf.Fill('*', aBuf.MaxLength());
       
   140 			return;
       
   141 			}
       
   142 		if (len == 0)
       
   143 			return;
       
   144 		for (;;)
       
   145 			{
       
   146 			aBuf.AppendFormat(_L("%02X"), *p++ & 0xFF);
       
   147 			if (--len == 0)
       
   148 				break;
       
   149 			aBuf.Append(TChar(':'));
       
   150 			}
       
   151 		}
       
   152 
       
   153 	inline static TRawAddr& Cast(const TSockAddr& aAddr)
       
   154 		{
       
   155 		return *((TRawAddr *)&aAddr); //lint !e1773 // standard way to implement Cast
       
   156 		}
       
   157 	inline static TRawAddr& Cast(const TSockAddr* aAddr)
       
   158 		{
       
   159 		return *((TRawAddr *)aAddr); //lint !e1773 // standard way to implement Cast
       
   160 		}
       
   161 	};
       
   162 
       
   163 //
       
   164 CIpAdmEngine::~CIpAdmEngine()
       
   165 	{
       
   166 	//
       
   167 	// Ordering is important... Do not close iSS before
       
   168 	// all sockets associated with it have been closed!
       
   169 	//
       
   170 	iFS.Close();
       
   171 	iSS.Close();
       
   172 	}
       
   173 
       
   174 void CIpAdmEngine::ConstructL()
       
   175 	{
       
   176 	//
       
   177 	// Start Socket Reader activity
       
   178 	//
       
   179 	CheckResultL(_L("Active Scheduler"), CActiveScheduler::Current() == NULL);
       
   180 	CheckResultL(_L("Connect to File server"), iFS.Connect());
       
   181 	CheckResultL(_L("Connect to Socket server"), iSS.Connect());
       
   182 	}
       
   183 
       
   184 
       
   185 LOCAL_C void AppendIpAddress(TDes &buf, const TDesC &aLabel, const TInetAddr &aAddr, TInt aSkip = 1)
       
   186 	{
       
   187 	if (aSkip && aAddr.IsUnspecified())
       
   188 		return;
       
   189 	TBuf<64> out;
       
   190 	buf.Append(aLabel);
       
   191 #ifdef HURRICANE_INSOCK
       
   192 	aAddr.Output(out);
       
   193 #else
       
   194 	aAddr.OutputWithScope(out);
       
   195 #endif
       
   196 	buf.Append(out);
       
   197 	}
       
   198 
       
   199 LOCAL_C void AppendRawAddress(TDes &buf, const TDesC &aLabel, const TSockAddr &aAddr)
       
   200 	{
       
   201 	if (aAddr.Family() == KAFUnspec)
       
   202 		return;
       
   203 	TBuf<100> out;
       
   204 	buf.Append(aLabel);
       
   205 	TRawAddr::Cast(aAddr).Output(out);
       
   206 	buf.Append(out);
       
   207 	}
       
   208 
       
   209 LOCAL_C void AppendIpMask(TDes &buf, const TInetAddr &aAddr)
       
   210 	{
       
   211 	if (aAddr.Family() == KAfInet6)
       
   212 		buf.AppendFormat(_L("/%d"), MaskLength(aAddr.Ip6Address()));
       
   213 	else
       
   214 		buf.AppendFormat(_L("/%d"), MaskLength(aAddr.Address())); 
       
   215 	}
       
   216 
       
   217 void CIpAdmEngine::Show(TInt /*aVersion*/, const TSoInetInterfaceInfo &aInfo)
       
   218 	{
       
   219 	TBuf<1000> buf;
       
   220 	buf = _L("if ");
       
   221 	AppendInterfaceStatus(buf, aInfo.iState);
       
   222 	AppendInterfaceName(buf, aInfo.iName);
       
   223 	AppendIpAddress(buf, _L(" addr="), (const TInetAddr &)aInfo.iAddress, 0);
       
   224 	AppendIpMask(buf, (const TInetAddr &)aInfo.iNetMask);
       
   225 	AppendIpAddress(buf, _L(" bcast="), (const TInetAddr &)aInfo.iBrdAddr);
       
   226 	AppendIpAddress(buf, _L(" gw="), (const TInetAddr &)aInfo.iDefGate);
       
   227 	AppendIpAddress(buf, _L(" ns1="), (const TInetAddr &)aInfo.iNameSer1);
       
   228 	AppendIpAddress(buf, _L(" ns2="), (const TInetAddr &)aInfo.iNameSer2);
       
   229 	AppendRawAddress(buf, _L(" hwa="), aInfo.iHwAddr);
       
   230 	buf.AppendFormat(_L(" Mtu=%d, SM=%d, F=%x"), aInfo.iMtu, aInfo.iSpeedMetric, (TUint)aInfo.iFeatures);
       
   231 	ShowText(buf);
       
   232 	}
       
   233 
       
   234 void CIpAdmEngine::Show(TInt /*aVersion*/, const TSoInetRouteInfo &aInfo)
       
   235 	{
       
   236 	TBuf<1000> buf;
       
   237 	buf = _L("rt");
       
   238 	AppendRouteType(buf, aInfo.iType);
       
   239 	AppendRouteState(buf, aInfo.iState);
       
   240 	AppendIpAddress(buf, _L(""), (const TInetAddr &)aInfo.iDstAddr, 0);
       
   241 	AppendIpMask(buf, (const TInetAddr &)aInfo.iNetMask);
       
   242 	// the iIfAddr is actually the src address to be used for this route destination
       
   243 	AppendIpAddress(buf, _L(" src="), (const TInetAddr &)aInfo.iIfAddr);
       
   244 	if (aInfo.iGateway.Family() == KAfInet6 || aInfo.iGateway.Family() == KAfInet)
       
   245 		AppendIpAddress(buf, _L(" gw="), (const TInetAddr &)aInfo.iGateway);
       
   246 	else
       
   247 		AppendRawAddress(buf, _L(" hwa="), aInfo.iGateway);
       
   248 	buf.AppendFormat(_L(" M=%d"), aInfo.iMetric);
       
   249 	ShowText(buf);
       
   250 	}
       
   251 
       
   252 void CIpAdmEngine::ListInterfaces(TInt aVersion, const TDesC &aProtocol)
       
   253 	{
       
   254 	RSocket socket;
       
   255 
       
   256 	if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone)
       
   257 		return;
       
   258 	if (socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl) == KErrNone)
       
   259 		{
       
   260 		TPckgBuf<TSoInetInterfaceInfo> opt;
       
   261 		while (socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
       
   262 			Show(aVersion, opt());
       
   263 		}
       
   264 	socket.Close();
       
   265 	}
       
   266 
       
   267 void CIpAdmEngine::ListRoutes(TInt aVersion, const TDesC &aProtocol)
       
   268 	{
       
   269 	RSocket socket;
       
   270 
       
   271 	if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone)
       
   272 		return;
       
   273 	if (socket.SetOpt(KSoInetEnumRoutes, KSolInetRtCtrl) == KErrNone)
       
   274 		{
       
   275 		TPckgBuf<TSoInetRouteInfo> opt;
       
   276 		while (socket.GetOpt(KSoInetNextRoute, KSolInetRtCtrl, opt) == KErrNone)
       
   277 			Show(aVersion, opt());
       
   278 		}
       
   279 	socket.Close();
       
   280 	}
       
   281 
       
   282 class TParser : public TLex
       
   283 	{
       
   284 public:
       
   285 	TParser(const TDesC &aStr);
       
   286 	void NextToken();
       
   287 	int SkipSpaceAndMark();
       
   288 	TInt ParameterValue(const TDesC &aKey, TInt &aValue, const TInt aDefault = 0);
       
   289 	TInt ParameterValue(const TDesC &aKey, TInetAddr &aValue);
       
   290 	TLexMark iLine;
       
   291 	TLexMark iCurrent;
       
   292 	TPtrC iLastLine;
       
   293 	TPtrC Line();
       
   294 	inline void MarkLine() { iCurrent = iLine; iOpen = 1; }
       
   295 	TPtrC iToken;
       
   296 	TInt iOpen;
       
   297 	TInt iFirst;	// Non-zero, if next token is first in line
       
   298 	};
       
   299 
       
   300 #pragma warning (disable:4097)
       
   301 TParser::TParser(const TDesC &aStr) : TLex(aStr), iLine(), iCurrent(), iLastLine(), iToken(), iOpen(0), iFirst(1)
       
   302 	{
       
   303 	Mark(iLine);
       
   304 	MarkLine();
       
   305 	}
       
   306 #pragma warning (default:4097)
       
   307 
       
   308 //
       
   309 // Return current line as a descriptor
       
   310 // (and skip to the next line, if not fully parsed)
       
   311 //
       
   312 TPtrC TParser::Line()
       
   313 	{
       
   314 	if (iOpen)
       
   315 		{
       
   316 		// Line not fully parsed yet, search to the EOL
       
   317 		while (!Eos())
       
   318 			{
       
   319 			TChar ch = Get();
       
   320 			if (ch == '\n' || ch == '\r')
       
   321 				{
       
   322 				iLastLine.Set(MarkedToken(iCurrent));
       
   323 				iOpen = 0;
       
   324 				Mark(iLine);
       
   325 				break;
       
   326 				}
       
   327 			}
       
   328 		}
       
   329 	return iLastLine;
       
   330 	}
       
   331 //
       
   332 // Skip white space and mark, including comments!
       
   333 //
       
   334 int TParser::SkipSpaceAndMark()
       
   335 	{
       
   336 	TChar ch;
       
   337 	TInt comment = 0;
       
   338 	TInt newline = 0;
       
   339 
       
   340 	while (!Eos())
       
   341 		{
       
   342 		ch = Get();
       
   343 		if (ch =='\n')
       
   344 			{
       
   345 			comment = 0;
       
   346 			newline = 1;
       
   347 			if (iOpen)
       
   348 				{
       
   349 				iLastLine.Set(MarkedToken(iCurrent));
       
   350 				iOpen = 0;
       
   351 				}
       
   352 			Mark(iLine);
       
   353 			}
       
   354 		else if (comment || ch == '#')
       
   355 			comment = 1;
       
   356 		else if (!ch.IsSpace())
       
   357 			{
       
   358 			UnGet();
       
   359 			break;
       
   360 			}
       
   361 		}
       
   362 	Mark();
       
   363 	return newline;
       
   364 	}
       
   365 
       
   366 //
       
   367 // Extract Next token and return
       
   368 //
       
   369 void TParser::NextToken()
       
   370 	{
       
   371 	if (SkipSpaceAndMark())
       
   372 		iFirst = 1;		// New line!
       
   373 	if (Eos())
       
   374 		{
       
   375 		iFirst = -1;
       
   376 		return;
       
   377 		}
       
   378 	while (!Eos())
       
   379 		{
       
   380 		TChar ch = Peek();
       
   381 		if (ch == '#' || ch.IsSpace())
       
   382 			break;
       
   383 		Inc();
       
   384 		}
       
   385 	iToken.Set(MarkedToken());
       
   386 	iFirst = SkipSpaceAndMark();
       
   387 	}
       
   388 
       
   389 TInt TParser::ParameterValue(const TDesC &aKey, TInt &aValue, const TInt aDefault)
       
   390 	{
       
   391 	if (aKey.Compare(iToken) != 0)
       
   392 		return KErrNotFound;		// Doesn't match, do nothing
       
   393 	//
       
   394 	// When the keyword matches, return is always KErrNone
       
   395 	// (caller must deduce errors by aDefault.
       
   396 	//
       
   397 	if (iFirst)
       
   398 		aValue = aDefault;
       
   399 	else if (Val(aValue) == KErrNone)
       
   400 		iFirst = SkipSpaceAndMark();
       
   401 	else
       
   402 		aValue = aDefault;
       
   403 	return KErrNone;
       
   404 	}
       
   405 
       
   406 TInt TParser::ParameterValue(const TDesC &aKey, TInetAddr &aValue)
       
   407 	{
       
   408 	if (aKey.Compare(iToken) != 0)
       
   409 		return KErrNotFound;		// Doesn't match, do nothing
       
   410 	//
       
   411 	// When the keyword matches, return is always KErrNone
       
   412 	// (caller must deduce errors by aDefault.
       
   413 	//
       
   414 	if (!iFirst)
       
   415 		{
       
   416 		NextToken();
       
   417 		if (aValue.Input(iToken) == KErrNone)
       
   418 			return KErrNone;
       
   419 		}
       
   420 	aValue.SetFamily(0);
       
   421 	return KErrNone;
       
   422 	}
       
   423 
       
   424 
       
   425 void CIpAdmEngine::AddRoutes(const TDesC &aProtocol)
       
   426 	{
       
   427 	TInt err = KErrNone;
       
   428 	RSocket socket;
       
   429 
       
   430 	if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone)
       
   431 		return;
       
   432 
       
   433 	HBufC *buf = NULL;
       
   434 #ifndef __DATA_CAGING__
       
   435 	TRAP(err, buf = UnicodeLoad::LoadL(iFS, DEFAULT_ROUTES_FILE));
       
   436 	if (CheckResult(DEFAULT_ROUTES_FILE, err))
       
   437 #else // __DATA_CAGING__
       
   438 // get private path
       
   439 	TFileName filename;
       
   440 	RFs theFS;
       
   441 
       
   442 	theFS.Connect();
       
   443 	theFS.PrivatePath(filename);
       
   444 	theFS.Close();
       
   445 	filename.Append(DEFAULT_ROUTES_FILE);
       
   446 
       
   447 	TRAP(err, buf = UnicodeLoad::LoadL(iFS, filename));
       
   448 	if (CheckResult(filename, err))
       
   449 #endif // __DATA_CAGING__
       
   450 		{
       
   451 		socket.Close();
       
   452 		return;
       
   453 		}
       
   454 	//lint -save -e613 Trapped above
       
   455 	TParser inifile(*buf); //lint -restore
       
   456 	TInt route_count = 0;
       
   457 	TInt if_count = 0;
       
   458 	while (!err)
       
   459 		{
       
   460 		// Skip until first token in line
       
   461 		while (inifile.iFirst == 0)
       
   462 			inifile.NextToken();
       
   463 		if (inifile.iFirst < 0)
       
   464 			break;
       
   465 
       
   466 		//
       
   467 		// The route file is a simple list of lines with following format
       
   468 		//
       
   469 		inifile.NextToken();
       
   470 		inifile.MarkLine();
       
   471 		if ((inifile.iToken.Compare(_L("route-add")) == 0))
       
   472 			{
       
   473 			//    route-add destination netmask metric gateway interface
       
   474 			//
       
   475 			// all except the "metric" are assumed to be addresses
       
   476 			//
       
   477 			TPckgBuf<TSoInetRouteInfo> opt;
       
   478 			opt().iType = ERtUser;
       
   479 			opt().iState = ERtReady;
       
   480 			opt().iIfAddr.SetFamily(KAFUnspec);
       
   481 			for (int i = 0; !err && inifile.iFirst == 0; ++i)
       
   482 				{
       
   483 				switch (i)
       
   484 					{
       
   485 					case 0:	// Destination
       
   486 						inifile.NextToken();
       
   487 						err = (TInetAddr::Cast(opt().iDstAddr)).Input(inifile.iToken);
       
   488 						break;
       
   489 					case 1: // Netmask
       
   490 						inifile.NextToken();
       
   491 						err = (TInetAddr::Cast(opt().iNetMask)).Input(inifile.iToken);
       
   492 						break;
       
   493 					case 2:	// metric
       
   494 						err = inifile.Val(opt().iMetric);
       
   495 						break;
       
   496 					case 3:	// Gateway
       
   497 						inifile.NextToken();
       
   498 						if (inifile.iToken.Compare(_L("-")) == 0)
       
   499 							opt().iGateway.SetFamily(KAFUnspec);
       
   500 						else
       
   501 							err = (TInetAddr::Cast(opt().iGateway)).Input(inifile.iToken);
       
   502 						break;
       
   503 					case 4: // Interface
       
   504 						inifile.NextToken();
       
   505 						if (inifile.iToken.Compare(_L("-")) == 0)
       
   506 							opt().iIfAddr.SetFamily(KAFUnspec);
       
   507 						else
       
   508 							err = (TInetAddr::Cast(opt().iIfAddr)).Input(inifile.iToken);
       
   509 						break;
       
   510 					default:
       
   511 						inifile.NextToken();
       
   512 						break;
       
   513 					}
       
   514 				inifile.SkipSpaceAndMark();
       
   515 				}
       
   516 			if (err)
       
   517 				{
       
   518 				ShowText(_L("Syntax error on line"));
       
   519 				ShowText(inifile.Line());
       
   520 				break;
       
   521 				}
       
   522 			else if (CheckResult(inifile.Line(), socket.SetOpt(KSoInetAddRoute, KSolInetRtCtrl, opt)) == KErrNone)
       
   523 				route_count++;
       
   524 			}
       
   525 		else if ((inifile.iToken.Compare(_L("ifconfig")) == 0))
       
   526 			{
       
   527 			//
       
   528 			// For now only simple format
       
   529 			//
       
   530 			//	ifconfig interface [address [remote]] [parameters]
       
   531 			//
       
   532 			//  perameters can be
       
   533 			//
       
   534 			//	prefix n	netmask (ip4)/prefix (ip6) [default 32/128]. This *IS* not same
       
   535 			//				as Unix ifconfig. Here the value tells whether a "single address"
       
   536 			//				or netmask/prefix configuration is to be performed.
       
   537 			//
       
   538 			//		*NOTE*	prefix splits the bits in the address into two sections: (prefix,id)
       
   539 			//				if prefix part is non-ZERO, it will be added as if router had sent
       
   540 			//				RA with prefix option with L=1, A=1
       
   541 			//				if id part is non-ZERO, it will be processed as interface id (alias
       
   542 			//				keyword will control whether this is primary or additional).
       
   543 			//
       
   544 			//		*NOTE*	prefix 128 => id part is zero length, assumed ZERO
       
   545 			//				prefix 0 => prefix part is zero length, and treated as ZERO
       
   546 			//
       
   547 			//		*NOTE*	If configuring for single address, do not specify prefix!
       
   548 			//
       
   549 			//	alias		specify additional network address ([address] required)
       
   550 			//				'alias' is not present, but [address] is, then the primary
       
   551 			//				network address is configured.
       
   552 			//	delete		remove specified network address
       
   553 			//	down		mark interface down
       
   554 			//	up			mark interface up
       
   555 			//	metric n	set metric to n
       
   556 			//	mtu n		set MTU to n
       
   557 			//	ns1 address	nameserver 1 address
       
   558 			//	ns2 address	nameserver 2 address
       
   559 			//	proxy		speficy address as proxy
       
   560 			//	anycast		specify address as anycast
       
   561 			//
       
   562 
       
   563 			TPckgBuf<TSoInet6InterfaceInfo> opt;
       
   564 #if 1
       
   565 			opt().iDoState = 0;
       
   566 			opt().iDoId = 0;
       
   567 			opt().iDoPrefix = 0;
       
   568 			opt().iDoAnycast = 0;
       
   569 #ifndef HURRICANE_INSOCK
       
   570 			opt().iDoProxy = 0;
       
   571 #endif
       
   572 			opt().iAlias = 0;
       
   573 			opt().iDelete = 0;
       
   574 			opt().iAddress.SetFamily(0);
       
   575 			opt().iDefGate.SetFamily(0);
       
   576 			opt().iNetMask.SetFamily(0);
       
   577 			opt().iNameSer1.SetFamily(0);
       
   578 			opt().iNameSer2.SetFamily(0);
       
   579 			opt().iMtu = 0;
       
   580 			opt().iSpeedMetric = 0;
       
   581 #else
       
   582 			// unfortunately, this does not work.. "has initialized data" in MARM compile!
       
   583 			static const TSoInet6InterfaceInfo init_opt;
       
   584 			opt() = init_opt;
       
   585 #endif
       
   586 			TInt prefix = -1;
       
   587 			for (int i = 0; !err && inifile.iFirst == 0; ++i)
       
   588 				{
       
   589 				inifile.NextToken();
       
   590 				switch (i)
       
   591 					{
       
   592 					case 0:	// Interface Name
       
   593 						opt().iName = inifile.iToken;
       
   594 						opt().iTag = inifile.iToken;
       
   595 						break;
       
   596 					case 1: // Address
       
   597 						if ((TInetAddr::Cast(opt().iAddress)).Input(inifile.iToken) != KErrNone)
       
   598 							{
       
   599 							i = 2;	// We won't have remote address either!
       
   600 							goto parameters; //lint !e801 // no clean way to do it without goto
       
   601 							}
       
   602 						break;
       
   603 					case 2: // Remote Address
       
   604 						if ((TInetAddr::Cast(opt().iDefGate)).Input(inifile.iToken) == KErrNone)
       
   605 							break;
       
   606 						//lint -fallthrough
       
   607 					default:
       
   608 parameters:
       
   609 						if (opt().iDoState == 0)
       
   610 							{
       
   611 							if (inifile.iToken.Compare(_L("down")) == 0)
       
   612 								{
       
   613 								opt().iState = EIfDown;
       
   614 								opt().iDoState = 1;
       
   615 								break;
       
   616 								}
       
   617 							if (inifile.iToken.Compare(_L("up")) == 0)
       
   618 								{
       
   619 								opt().iState = EIfUp;
       
   620 								opt().iDoState = 1;
       
   621 								break;
       
   622 								}
       
   623 							}
       
   624 						if (opt().iDoAnycast == 0 &&
       
   625 #ifndef HURRICANE_INSOCK
       
   626 							opt().iDoProxy == 0 &&
       
   627 #endif
       
   628 							prefix < 0)
       
   629 							{
       
   630 							// Only one of 'proxy' or 'anycast' can be present. Also, prefix must not
       
   631 							// be present.
       
   632 							if (inifile.iToken.Compare(_L("anycast")) == 0)
       
   633 								{
       
   634 								opt().iDoAnycast = 1;
       
   635 								break;
       
   636 								}
       
   637 							else if (inifile.iToken.Compare(_L("proxy")) == 0)
       
   638 								{
       
   639 #ifndef HURRICANE_INSOCK
       
   640 								opt().iDoProxy = 1;
       
   641 #endif
       
   642 								break;
       
   643 								}
       
   644 							}
       
   645 						if (opt().iNameSer1.Family() == 0 && inifile.ParameterValue(_L("ns1"), opt().iNameSer1) == KErrNone)
       
   646 							break;
       
   647 						if (opt().iNameSer2.Family() == 0 && inifile.ParameterValue(_L("ns2"), opt().iNameSer2) == KErrNone)
       
   648 							break;
       
   649 						if (opt().iDelete == 0 && inifile.iToken.Compare(_L("delete")) == 0)
       
   650 							{
       
   651 							opt().iDelete = 1;
       
   652 							break;
       
   653 							}
       
   654 						if (opt().iAlias == 0 && inifile.iToken.Compare(_L("alias")) == 0)
       
   655 							{
       
   656 							opt().iAlias = 1;
       
   657 							break;
       
   658 							}
       
   659 						if (opt().iMtu == 0 && inifile.ParameterValue(_L("mtu"), opt().iMtu) == KErrNone)
       
   660 							break;
       
   661 						if (opt().iSpeedMetric == 0 && inifile.ParameterValue(_L("metric"), opt().iSpeedMetric) == KErrNone)
       
   662 							break;
       
   663 						if (opt().iDoAnycast == 0 &&
       
   664 #ifndef HURRICANE_INSOCK
       
   665 							opt().iDoProxy == 0 &&
       
   666 #endif
       
   667 							prefix < 0 &&
       
   668 							inifile.ParameterValue(_L("prefix"), prefix, 129) == KErrNone)
       
   669 							{
       
   670 							// prefix == 129, if value is missing => Error
       
   671 							if (prefix > 128)
       
   672 								err = KErrArgument;
       
   673 							break;
       
   674 							}
       
   675 						err = KErrGeneral;
       
   676 						break;
       
   677 					}
       
   678 					inifile.SkipSpaceAndMark();
       
   679 				}
       
   680 			if (!err)
       
   681 				{
       
   682 				// Munge the prefix information into TSoInet6InterfaceInfo
       
   683 				if (prefix < 0)
       
   684 					{
       
   685 					// No prefix present, iNetMask is left unspecified,
       
   686 					// request "single address" processing (prefix = 128)
       
   687 					opt().iDoId = 1;
       
   688 					opt().iDoPrefix = 1;
       
   689 					}
       
   690 				else if (opt().iAddress.Family() == KAfInet && prefix <= 32)
       
   691 					{
       
   692 					// IPv4 processing -- defines the netmask
       
   693 					const TUint32 mask = ~0UL << (32 - prefix);
       
   694 					const TUint32 addr = opt().iAddress.Address();
       
   695 					TInetAddr::Cast(opt().iNetMask).SetAddress(mask);
       
   696 					if (mask & addr)
       
   697 						opt().iDoPrefix = 1;
       
   698 					if ((~mask) & addr)
       
   699 						opt().iDoId = 1;
       
   700 					}
       
   701 				else if (opt().iAddress.Family() == KAfInet6 && prefix <= 128)
       
   702 					{
       
   703 					// IPv6 processing
       
   704 					TInetAddr p;
       
   705 					// Is Prefix part all zeroes?
       
   706 					p.Prefix(TInetAddr::Cast(opt().iAddress), prefix);
       
   707 					if (!p.Ip6Address().IsUnspecified())
       
   708 						opt().iDoPrefix = 1;
       
   709 					TInetAddr::Cast(opt().iNetMask).PrefixMask(prefix);
       
   710 					// Is Id part all zeroes?
       
   711 					p.SetAddress(TInetAddr::Cast(opt().iAddress).Ip6Address());
       
   712 					const TIp6Addr addr = p.Ip6Address();
       
   713 					const TIp6Addr mask = TInetAddr::Cast(opt().iNetMask).Ip6Address();
       
   714 					if ((addr.u.iAddr32[0] & ~mask.u.iAddr32[0]) != 0 ||
       
   715 						(addr.u.iAddr32[1] & ~mask.u.iAddr32[1]) != 0 ||
       
   716 						(addr.u.iAddr32[2] & ~mask.u.iAddr32[2]) != 0 ||
       
   717 						(addr.u.iAddr32[3] & ~mask.u.iAddr32[3]) != 0)
       
   718 						opt().iDoId = 1;
       
   719 					}
       
   720 				else
       
   721 					{
       
   722 					// incorrect of prefix value
       
   723 					err = KErrArgument;
       
   724 					}
       
   725 				}
       
   726 			if (err)
       
   727 				{
       
   728 				ShowText(_L("Syntax error on line"));
       
   729 				ShowText(inifile.Line());
       
   730 				break;
       
   731 				}
       
   732 			else if (CheckResult(inifile.Line(), socket.SetOpt(KSoInetConfigInterface, KSolInetIfCtrl, opt)) == KErrNone)
       
   733 				if_count++;
       
   734 			}
       
   735 #ifndef HURRICANE_INSOCK
       
   736 		else if ((inifile.iToken.Compare(_L("setscope")) == 0))
       
   737 			{
       
   738 			//
       
   739 			// For now only simple format
       
   740 			//
       
   741 			//	setscope interface interface2 level
       
   742 			//
       
   743 			//  perameters can be
       
   744 			//
       
   745 			//	interface	the name of the interface to be change
       
   746 			//	interface2	the name of the interface to used as a source for the scope values
       
   747 			//	scope		the scope of the join point [2..16]
       
   748 
       
   749 			TPckgBuf<TSoInetIfQuery> opt1;
       
   750 			TPckgBuf<TSoInetIfQuery> opt2;
       
   751 			TInt scope = -1;
       
   752 			TInt i = 0;
       
   753 			for (i = 0; !err && inifile.iFirst == 0; ++i)
       
   754 				{
       
   755 				inifile.NextToken();
       
   756 				switch (i)
       
   757 					{
       
   758 					case 0:	// Interface Name (to modify)
       
   759 						opt1().iName = inifile.iToken;
       
   760 						err = CheckResult(inifile.iToken, socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt1));
       
   761 						break;
       
   762 					case 1: // Interface Name (the source)
       
   763 						opt2().iName = inifile.iToken;
       
   764 						err = CheckResult(inifile.iToken, socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt2));
       
   765 						break;
       
   766 					case 2: // Scope Level
       
   767 						err = inifile.ParameterValue(_L("level"), scope);
       
   768 						break;
       
   769 					default:
       
   770 						err = KErrArgument;
       
   771 						break;
       
   772 					}
       
   773 				inifile.SkipSpaceAndMark();
       
   774 				}
       
   775 			if (err || scope < 2 || scope > 16)
       
   776 				{
       
   777 				ShowText(_L("Syntax error on line"));
       
   778 				ShowText(inifile.Line());
       
   779 				break;
       
   780 				}
       
   781 			//
       
   782 			// Build a new scope id vector
       
   783 			//
       
   784 			scope -= 1; // scope array is indexed from 0
       
   785 #if 0
       
   786 			for (i = 0; ++i < scope;)
       
   787 				opt1().iZone[i] = ~opt1().iZone[0];
       
   788 			for ( ;scope < STATIC_CAST(TInt, sizeof(opt1().iZone) / sizeof(opt1().iZone[0])); ++scope)
       
   789 				opt1().iZone[scope] = opt2().iZone[scope];
       
   790 #else
       
   791 			opt1().iZone[scope] = opt2().iZone[scope];
       
   792 #endif
       
   793 			opt1().iIndex = opt1().iZone[0];
       
   794 			err = CheckResult(inifile.Line(), socket.SetOpt(KSoInetIfQuerySetScope, KSolInetIfQuery, opt1));
       
   795 			}
       
   796 #endif
       
   797 		}
       
   798 	delete buf;
       
   799 	TBuf<80> text;
       
   800 	text.Format(_L("Added %d routes, configured %d interfaces"), route_count, if_count);
       
   801 	ShowText(text);
       
   802 	socket.Close();
       
   803 	}
       
   804 
       
   805 void CIpAdmEngine::HandleCommandL(TInt aCommand)
       
   806 	{
       
   807 	switch (aCommand)
       
   808 		{
       
   809 		case EIpAdmInterfaces:
       
   810 			ListInterfaces(4,_L("udp"));
       
   811 //			ListInterfaces(6,_L("udp6"));
       
   812 			break;
       
   813 		case EIpAdmRoutes:
       
   814 			ListRoutes(4, _L("udp"));
       
   815 //			ListRoutes(6, _L("udp6"));
       
   816 			break;
       
   817 		case EIpAdmAddRoutes:
       
   818 			AddRoutes(_L("udp"));
       
   819 			break;
       
   820 		default:
       
   821 			break;
       
   822 		}
       
   823 	}
       
   824 
       
   825 
       
   826 //
       
   827 // CIpAdmEngine::CheckResult
       
   828 //	Output success or fail message, returns the error code
       
   829 //
       
   830 TInt CIpAdmEngine::CheckResult(const TDesC &aText, TInt aResult)
       
   831 	{
       
   832 	if (aResult == KErrNone)
       
   833 		return KErrNone;
       
   834 
       
   835 	TBuf<100> err;
       
   836 	CEikonEnv::Static()->GetErrorText(err, aResult);
       
   837 
       
   838 	TBuf<200> str(aText);
       
   839 	str.AppendFormat(_L(" returned with [%s] "), err.PtrZ());
       
   840 	iAppView->Write(str);
       
   841 
       
   842 	return aResult;
       
   843 	}
       
   844 //
       
   845 // CIpAdmEngine::CheckResultL
       
   846 //	Output success or fail message, and Leave if the code is not
       
   847 //	KErrNone.
       
   848 //
       
   849 void CIpAdmEngine::CheckResultL(const TDesC &aText, TInt aResult)
       
   850 	{
       
   851 	if (CheckResult(aText, aResult) != KErrNone)
       
   852 		User::Leave(aResult);
       
   853 	}
       
   854 
       
   855 void CIpAdmEngine::ShowText(const TDesC &aText)
       
   856 	{
       
   857 	iAppView->Write(aText);
       
   858 	}
       
   859