diff -r 4ca382093dae -r 493058e57c8c networkingutils/ipadministrationtool/src/engine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkingutils/ipadministrationtool/src/engine.cpp Wed Sep 01 12:30:50 2010 +0100 @@ -0,0 +1,859 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// engine.cpp - IP administration tool engine +// + +#include +#include "ipadm.h" +#include "engine.h" + +#include "uniload.h" + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#endif + +#ifndef __SECURE_DATA__ +#define DEFAULT_ROUTES_FILE _L("C:\\Data\\IpAdm\\route.ini") +#else +#define DEFAULT_ROUTES_FILE _L("route.ini") +#endif + +LOCAL_C void AppendInterfaceStatus(TDes& buf, const TInt aStatus) + { + switch (aStatus) + { + case EIfPending: buf.Append(_L("PEND ")); break; + case EIfUp: break; + case EIfBusy: buf.Append(_L("BUSY ")); break; + case EIfDown: buf.Append(_L("DOWN ")); break; + default: buf.Append(_L("???? ")); break; + } + } + +LOCAL_C void AppendInterfaceName(TDes& buf, const TName& aName) + { + if (aName.Length() > 0) + { + buf.Append(aName); + } + else + { + buf.Append(_L("default")); + } + } + +LOCAL_C void AppendRouteType(TDes& buf, const TInt aType) + { + switch (aType) + { + case ERtNormal: buf.Append(_L(" ")); break; + case ERtUser: buf.Append(_L("u ")); break; + case ERtIcmpAdd: buf.Append(_L("- ")); break; // for IPv6, this is ND entry + case ERtIcmpDel: buf.Append(_L("d ")); break; + default: buf.Append(_L("? ")); break; + } + } + +LOCAL_C void AppendRouteState(TDes& buf, const TInt aState) + { + switch (aState) + { + case ERtNone: buf.Append(_L("NONE ")); break; + case ERtPending: buf.Append(_L("PEND ")); break; + case ERtBusy: buf.Append(_L("BUSY ")); break; + case ERtReady: break; + case ERtDown: buf.Append(_L("DOWN ")); break; + default: buf.Append(_L("???? ")); break; + } + } + +// +// +// Just count the number of rightmost zeroes in an IPv6 address +// and return (128 - count). +// +LOCAL_C TInt MaskLength(const TIp6Addr &aAddr) + { + TInt count = 0; + for (TInt i = sizeof(aAddr.u.iAddr8) / sizeof(aAddr.u.iAddr8[0]); --i >= 0; ) + { + if (aAddr.u.iAddr8[i]) + { + TUint8 nonZeroByte = aAddr.u.iAddr8[i]; + while ((nonZeroByte & 1) == 0) + { + count += 1; + nonZeroByte >>= 1; + } + break; + } + count += 8; + } + return 128-count; + } + + +LOCAL_C TInt MaskLength(TUint32 aAddr) + { + TInt count = 0; + // obviously, this is "brute force" counting + while (aAddr & 0x80000000) + { + count++; + aAddr <<= 1; + } + return count; + } + + +// TRawAddr +// ********* +// Lightweight internal help class for handling the link layer addresses +// +class TRawAddr : public TSockAddr + { +public: + + void Output(TDes& aBuf) const + { + TUint8* p = (TUint8*)UserPtr(); + TInt len = ((TSockAddr *)this)->GetUserLen(); //lint !e1773 // it's a kludge but works anyway + + aBuf.SetLength(0); + if (len == 0) + return; + if (aBuf.MaxLength() < len * 4) + { + aBuf.Fill('*', aBuf.MaxLength()); + return; + } + if (len == 0) + return; + for (;;) + { + aBuf.AppendFormat(_L("%02X"), *p++ & 0xFF); + if (--len == 0) + break; + aBuf.Append(TChar(':')); + } + } + + inline static TRawAddr& Cast(const TSockAddr& aAddr) + { + return *((TRawAddr *)&aAddr); //lint !e1773 // standard way to implement Cast + } + inline static TRawAddr& Cast(const TSockAddr* aAddr) + { + return *((TRawAddr *)aAddr); //lint !e1773 // standard way to implement Cast + } + }; + +// +CIpAdmEngine::~CIpAdmEngine() + { + // + // Ordering is important... Do not close iSS before + // all sockets associated with it have been closed! + // + iFS.Close(); + iSS.Close(); + } + +void CIpAdmEngine::ConstructL() + { + // + // Start Socket Reader activity + // + CheckResultL(_L("Active Scheduler"), CActiveScheduler::Current() == NULL); + CheckResultL(_L("Connect to File server"), iFS.Connect()); + CheckResultL(_L("Connect to Socket server"), iSS.Connect()); + } + + +LOCAL_C void AppendIpAddress(TDes &buf, const TDesC &aLabel, const TInetAddr &aAddr, TInt aSkip = 1) + { + if (aSkip && aAddr.IsUnspecified()) + return; + TBuf<64> out; + buf.Append(aLabel); +#ifdef HURRICANE_INSOCK + aAddr.Output(out); +#else + aAddr.OutputWithScope(out); +#endif + buf.Append(out); + } + +LOCAL_C void AppendRawAddress(TDes &buf, const TDesC &aLabel, const TSockAddr &aAddr) + { + if (aAddr.Family() == KAFUnspec) + return; + TBuf<100> out; + buf.Append(aLabel); + TRawAddr::Cast(aAddr).Output(out); + buf.Append(out); + } + +LOCAL_C void AppendIpMask(TDes &buf, const TInetAddr &aAddr) + { + if (aAddr.Family() == KAfInet6) + buf.AppendFormat(_L("/%d"), MaskLength(aAddr.Ip6Address())); + else + buf.AppendFormat(_L("/%d"), MaskLength(aAddr.Address())); + } + +void CIpAdmEngine::Show(TInt /*aVersion*/, const TSoInetInterfaceInfo &aInfo) + { + TBuf<1000> buf; + buf = _L("if "); + AppendInterfaceStatus(buf, aInfo.iState); + AppendInterfaceName(buf, aInfo.iName); + AppendIpAddress(buf, _L(" addr="), (const TInetAddr &)aInfo.iAddress, 0); + AppendIpMask(buf, (const TInetAddr &)aInfo.iNetMask); + AppendIpAddress(buf, _L(" bcast="), (const TInetAddr &)aInfo.iBrdAddr); + AppendIpAddress(buf, _L(" gw="), (const TInetAddr &)aInfo.iDefGate); + AppendIpAddress(buf, _L(" ns1="), (const TInetAddr &)aInfo.iNameSer1); + AppendIpAddress(buf, _L(" ns2="), (const TInetAddr &)aInfo.iNameSer2); + AppendRawAddress(buf, _L(" hwa="), aInfo.iHwAddr); + buf.AppendFormat(_L(" Mtu=%d, SM=%d, F=%x"), aInfo.iMtu, aInfo.iSpeedMetric, (TUint)aInfo.iFeatures); + ShowText(buf); + } + +void CIpAdmEngine::Show(TInt /*aVersion*/, const TSoInetRouteInfo &aInfo) + { + TBuf<1000> buf; + buf = _L("rt"); + AppendRouteType(buf, aInfo.iType); + AppendRouteState(buf, aInfo.iState); + AppendIpAddress(buf, _L(""), (const TInetAddr &)aInfo.iDstAddr, 0); + AppendIpMask(buf, (const TInetAddr &)aInfo.iNetMask); + // the iIfAddr is actually the src address to be used for this route destination + AppendIpAddress(buf, _L(" src="), (const TInetAddr &)aInfo.iIfAddr); + if (aInfo.iGateway.Family() == KAfInet6 || aInfo.iGateway.Family() == KAfInet) + AppendIpAddress(buf, _L(" gw="), (const TInetAddr &)aInfo.iGateway); + else + AppendRawAddress(buf, _L(" hwa="), aInfo.iGateway); + buf.AppendFormat(_L(" M=%d"), aInfo.iMetric); + ShowText(buf); + } + +void CIpAdmEngine::ListInterfaces(TInt aVersion, const TDesC &aProtocol) + { + RSocket socket; + + if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone) + return; + if (socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl) == KErrNone) + { + TPckgBuf opt; + while (socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone) + Show(aVersion, opt()); + } + socket.Close(); + } + +void CIpAdmEngine::ListRoutes(TInt aVersion, const TDesC &aProtocol) + { + RSocket socket; + + if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone) + return; + if (socket.SetOpt(KSoInetEnumRoutes, KSolInetRtCtrl) == KErrNone) + { + TPckgBuf opt; + while (socket.GetOpt(KSoInetNextRoute, KSolInetRtCtrl, opt) == KErrNone) + Show(aVersion, opt()); + } + socket.Close(); + } + +class TParser : public TLex + { +public: + TParser(const TDesC &aStr); + void NextToken(); + int SkipSpaceAndMark(); + TInt ParameterValue(const TDesC &aKey, TInt &aValue, const TInt aDefault = 0); + TInt ParameterValue(const TDesC &aKey, TInetAddr &aValue); + TLexMark iLine; + TLexMark iCurrent; + TPtrC iLastLine; + TPtrC Line(); + inline void MarkLine() { iCurrent = iLine; iOpen = 1; } + TPtrC iToken; + TInt iOpen; + TInt iFirst; // Non-zero, if next token is first in line + }; + +#pragma warning (disable:4097) +TParser::TParser(const TDesC &aStr) : TLex(aStr), iLine(), iCurrent(), iLastLine(), iToken(), iOpen(0), iFirst(1) + { + Mark(iLine); + MarkLine(); + } +#pragma warning (default:4097) + +// +// Return current line as a descriptor +// (and skip to the next line, if not fully parsed) +// +TPtrC TParser::Line() + { + if (iOpen) + { + // Line not fully parsed yet, search to the EOL + while (!Eos()) + { + TChar ch = Get(); + if (ch == '\n' || ch == '\r') + { + iLastLine.Set(MarkedToken(iCurrent)); + iOpen = 0; + Mark(iLine); + break; + } + } + } + return iLastLine; + } +// +// Skip white space and mark, including comments! +// +int TParser::SkipSpaceAndMark() + { + TChar ch; + TInt comment = 0; + TInt newline = 0; + + while (!Eos()) + { + ch = Get(); + if (ch =='\n') + { + comment = 0; + newline = 1; + if (iOpen) + { + iLastLine.Set(MarkedToken(iCurrent)); + iOpen = 0; + } + Mark(iLine); + } + else if (comment || ch == '#') + comment = 1; + else if (!ch.IsSpace()) + { + UnGet(); + break; + } + } + Mark(); + return newline; + } + +// +// Extract Next token and return +// +void TParser::NextToken() + { + if (SkipSpaceAndMark()) + iFirst = 1; // New line! + if (Eos()) + { + iFirst = -1; + return; + } + while (!Eos()) + { + TChar ch = Peek(); + if (ch == '#' || ch.IsSpace()) + break; + Inc(); + } + iToken.Set(MarkedToken()); + iFirst = SkipSpaceAndMark(); + } + +TInt TParser::ParameterValue(const TDesC &aKey, TInt &aValue, const TInt aDefault) + { + if (aKey.Compare(iToken) != 0) + return KErrNotFound; // Doesn't match, do nothing + // + // When the keyword matches, return is always KErrNone + // (caller must deduce errors by aDefault. + // + if (iFirst) + aValue = aDefault; + else if (Val(aValue) == KErrNone) + iFirst = SkipSpaceAndMark(); + else + aValue = aDefault; + return KErrNone; + } + +TInt TParser::ParameterValue(const TDesC &aKey, TInetAddr &aValue) + { + if (aKey.Compare(iToken) != 0) + return KErrNotFound; // Doesn't match, do nothing + // + // When the keyword matches, return is always KErrNone + // (caller must deduce errors by aDefault. + // + if (!iFirst) + { + NextToken(); + if (aValue.Input(iToken) == KErrNone) + return KErrNone; + } + aValue.SetFamily(0); + return KErrNone; + } + + +void CIpAdmEngine::AddRoutes(const TDesC &aProtocol) + { + TInt err = KErrNone; + RSocket socket; + + if (CheckResult(aProtocol, socket.Open(iSS, aProtocol)) != KErrNone) + return; + + HBufC *buf = NULL; +#ifndef __DATA_CAGING__ + TRAP(err, buf = UnicodeLoad::LoadL(iFS, DEFAULT_ROUTES_FILE)); + if (CheckResult(DEFAULT_ROUTES_FILE, err)) +#else // __DATA_CAGING__ +// get private path + TFileName filename; + RFs theFS; + + theFS.Connect(); + theFS.PrivatePath(filename); + theFS.Close(); + filename.Append(DEFAULT_ROUTES_FILE); + + TRAP(err, buf = UnicodeLoad::LoadL(iFS, filename)); + if (CheckResult(filename, err)) +#endif // __DATA_CAGING__ + { + socket.Close(); + return; + } + //lint -save -e613 Trapped above + TParser inifile(*buf); //lint -restore + TInt route_count = 0; + TInt if_count = 0; + while (!err) + { + // Skip until first token in line + while (inifile.iFirst == 0) + inifile.NextToken(); + if (inifile.iFirst < 0) + break; + + // + // The route file is a simple list of lines with following format + // + inifile.NextToken(); + inifile.MarkLine(); + if ((inifile.iToken.Compare(_L("route-add")) == 0)) + { + // route-add destination netmask metric gateway interface + // + // all except the "metric" are assumed to be addresses + // + TPckgBuf opt; + opt().iType = ERtUser; + opt().iState = ERtReady; + opt().iIfAddr.SetFamily(KAFUnspec); + for (int i = 0; !err && inifile.iFirst == 0; ++i) + { + switch (i) + { + case 0: // Destination + inifile.NextToken(); + err = (TInetAddr::Cast(opt().iDstAddr)).Input(inifile.iToken); + break; + case 1: // Netmask + inifile.NextToken(); + err = (TInetAddr::Cast(opt().iNetMask)).Input(inifile.iToken); + break; + case 2: // metric + err = inifile.Val(opt().iMetric); + break; + case 3: // Gateway + inifile.NextToken(); + if (inifile.iToken.Compare(_L("-")) == 0) + opt().iGateway.SetFamily(KAFUnspec); + else + err = (TInetAddr::Cast(opt().iGateway)).Input(inifile.iToken); + break; + case 4: // Interface + inifile.NextToken(); + if (inifile.iToken.Compare(_L("-")) == 0) + opt().iIfAddr.SetFamily(KAFUnspec); + else + err = (TInetAddr::Cast(opt().iIfAddr)).Input(inifile.iToken); + break; + default: + inifile.NextToken(); + break; + } + inifile.SkipSpaceAndMark(); + } + if (err) + { + ShowText(_L("Syntax error on line")); + ShowText(inifile.Line()); + break; + } + else if (CheckResult(inifile.Line(), socket.SetOpt(KSoInetAddRoute, KSolInetRtCtrl, opt)) == KErrNone) + route_count++; + } + else if ((inifile.iToken.Compare(_L("ifconfig")) == 0)) + { + // + // For now only simple format + // + // ifconfig interface [address [remote]] [parameters] + // + // perameters can be + // + // prefix n netmask (ip4)/prefix (ip6) [default 32/128]. This *IS* not same + // as Unix ifconfig. Here the value tells whether a "single address" + // or netmask/prefix configuration is to be performed. + // + // *NOTE* prefix splits the bits in the address into two sections: (prefix,id) + // if prefix part is non-ZERO, it will be added as if router had sent + // RA with prefix option with L=1, A=1 + // if id part is non-ZERO, it will be processed as interface id (alias + // keyword will control whether this is primary or additional). + // + // *NOTE* prefix 128 => id part is zero length, assumed ZERO + // prefix 0 => prefix part is zero length, and treated as ZERO + // + // *NOTE* If configuring for single address, do not specify prefix! + // + // alias specify additional network address ([address] required) + // 'alias' is not present, but [address] is, then the primary + // network address is configured. + // delete remove specified network address + // down mark interface down + // up mark interface up + // metric n set metric to n + // mtu n set MTU to n + // ns1 address nameserver 1 address + // ns2 address nameserver 2 address + // proxy speficy address as proxy + // anycast specify address as anycast + // + + TPckgBuf opt; +#if 1 + opt().iDoState = 0; + opt().iDoId = 0; + opt().iDoPrefix = 0; + opt().iDoAnycast = 0; +#ifndef HURRICANE_INSOCK + opt().iDoProxy = 0; +#endif + opt().iAlias = 0; + opt().iDelete = 0; + opt().iAddress.SetFamily(0); + opt().iDefGate.SetFamily(0); + opt().iNetMask.SetFamily(0); + opt().iNameSer1.SetFamily(0); + opt().iNameSer2.SetFamily(0); + opt().iMtu = 0; + opt().iSpeedMetric = 0; +#else + // unfortunately, this does not work.. "has initialized data" in MARM compile! + static const TSoInet6InterfaceInfo init_opt; + opt() = init_opt; +#endif + TInt prefix = -1; + for (int i = 0; !err && inifile.iFirst == 0; ++i) + { + inifile.NextToken(); + switch (i) + { + case 0: // Interface Name + opt().iName = inifile.iToken; + opt().iTag = inifile.iToken; + break; + case 1: // Address + if ((TInetAddr::Cast(opt().iAddress)).Input(inifile.iToken) != KErrNone) + { + i = 2; // We won't have remote address either! + goto parameters; //lint !e801 // no clean way to do it without goto + } + break; + case 2: // Remote Address + if ((TInetAddr::Cast(opt().iDefGate)).Input(inifile.iToken) == KErrNone) + break; + //lint -fallthrough + default: +parameters: + if (opt().iDoState == 0) + { + if (inifile.iToken.Compare(_L("down")) == 0) + { + opt().iState = EIfDown; + opt().iDoState = 1; + break; + } + if (inifile.iToken.Compare(_L("up")) == 0) + { + opt().iState = EIfUp; + opt().iDoState = 1; + break; + } + } + if (opt().iDoAnycast == 0 && +#ifndef HURRICANE_INSOCK + opt().iDoProxy == 0 && +#endif + prefix < 0) + { + // Only one of 'proxy' or 'anycast' can be present. Also, prefix must not + // be present. + if (inifile.iToken.Compare(_L("anycast")) == 0) + { + opt().iDoAnycast = 1; + break; + } + else if (inifile.iToken.Compare(_L("proxy")) == 0) + { +#ifndef HURRICANE_INSOCK + opt().iDoProxy = 1; +#endif + break; + } + } + if (opt().iNameSer1.Family() == 0 && inifile.ParameterValue(_L("ns1"), opt().iNameSer1) == KErrNone) + break; + if (opt().iNameSer2.Family() == 0 && inifile.ParameterValue(_L("ns2"), opt().iNameSer2) == KErrNone) + break; + if (opt().iDelete == 0 && inifile.iToken.Compare(_L("delete")) == 0) + { + opt().iDelete = 1; + break; + } + if (opt().iAlias == 0 && inifile.iToken.Compare(_L("alias")) == 0) + { + opt().iAlias = 1; + break; + } + if (opt().iMtu == 0 && inifile.ParameterValue(_L("mtu"), opt().iMtu) == KErrNone) + break; + if (opt().iSpeedMetric == 0 && inifile.ParameterValue(_L("metric"), opt().iSpeedMetric) == KErrNone) + break; + if (opt().iDoAnycast == 0 && +#ifndef HURRICANE_INSOCK + opt().iDoProxy == 0 && +#endif + prefix < 0 && + inifile.ParameterValue(_L("prefix"), prefix, 129) == KErrNone) + { + // prefix == 129, if value is missing => Error + if (prefix > 128) + err = KErrArgument; + break; + } + err = KErrGeneral; + break; + } + inifile.SkipSpaceAndMark(); + } + if (!err) + { + // Munge the prefix information into TSoInet6InterfaceInfo + if (prefix < 0) + { + // No prefix present, iNetMask is left unspecified, + // request "single address" processing (prefix = 128) + opt().iDoId = 1; + opt().iDoPrefix = 1; + } + else if (opt().iAddress.Family() == KAfInet && prefix <= 32) + { + // IPv4 processing -- defines the netmask + const TUint32 mask = ~0UL << (32 - prefix); + const TUint32 addr = opt().iAddress.Address(); + TInetAddr::Cast(opt().iNetMask).SetAddress(mask); + if (mask & addr) + opt().iDoPrefix = 1; + if ((~mask) & addr) + opt().iDoId = 1; + } + else if (opt().iAddress.Family() == KAfInet6 && prefix <= 128) + { + // IPv6 processing + TInetAddr p; + // Is Prefix part all zeroes? + p.Prefix(TInetAddr::Cast(opt().iAddress), prefix); + if (!p.Ip6Address().IsUnspecified()) + opt().iDoPrefix = 1; + TInetAddr::Cast(opt().iNetMask).PrefixMask(prefix); + // Is Id part all zeroes? + p.SetAddress(TInetAddr::Cast(opt().iAddress).Ip6Address()); + const TIp6Addr addr = p.Ip6Address(); + const TIp6Addr mask = TInetAddr::Cast(opt().iNetMask).Ip6Address(); + if ((addr.u.iAddr32[0] & ~mask.u.iAddr32[0]) != 0 || + (addr.u.iAddr32[1] & ~mask.u.iAddr32[1]) != 0 || + (addr.u.iAddr32[2] & ~mask.u.iAddr32[2]) != 0 || + (addr.u.iAddr32[3] & ~mask.u.iAddr32[3]) != 0) + opt().iDoId = 1; + } + else + { + // incorrect of prefix value + err = KErrArgument; + } + } + if (err) + { + ShowText(_L("Syntax error on line")); + ShowText(inifile.Line()); + break; + } + else if (CheckResult(inifile.Line(), socket.SetOpt(KSoInetConfigInterface, KSolInetIfCtrl, opt)) == KErrNone) + if_count++; + } +#ifndef HURRICANE_INSOCK + else if ((inifile.iToken.Compare(_L("setscope")) == 0)) + { + // + // For now only simple format + // + // setscope interface interface2 level + // + // perameters can be + // + // interface the name of the interface to be change + // interface2 the name of the interface to used as a source for the scope values + // scope the scope of the join point [2..16] + + TPckgBuf opt1; + TPckgBuf opt2; + TInt scope = -1; + TInt i = 0; + for (i = 0; !err && inifile.iFirst == 0; ++i) + { + inifile.NextToken(); + switch (i) + { + case 0: // Interface Name (to modify) + opt1().iName = inifile.iToken; + err = CheckResult(inifile.iToken, socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt1)); + break; + case 1: // Interface Name (the source) + opt2().iName = inifile.iToken; + err = CheckResult(inifile.iToken, socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt2)); + break; + case 2: // Scope Level + err = inifile.ParameterValue(_L("level"), scope); + break; + default: + err = KErrArgument; + break; + } + inifile.SkipSpaceAndMark(); + } + if (err || scope < 2 || scope > 16) + { + ShowText(_L("Syntax error on line")); + ShowText(inifile.Line()); + break; + } + // + // Build a new scope id vector + // + scope -= 1; // scope array is indexed from 0 +#if 0 + for (i = 0; ++i < scope;) + opt1().iZone[i] = ~opt1().iZone[0]; + for ( ;scope < STATIC_CAST(TInt, sizeof(opt1().iZone) / sizeof(opt1().iZone[0])); ++scope) + opt1().iZone[scope] = opt2().iZone[scope]; +#else + opt1().iZone[scope] = opt2().iZone[scope]; +#endif + opt1().iIndex = opt1().iZone[0]; + err = CheckResult(inifile.Line(), socket.SetOpt(KSoInetIfQuerySetScope, KSolInetIfQuery, opt1)); + } +#endif + } + delete buf; + TBuf<80> text; + text.Format(_L("Added %d routes, configured %d interfaces"), route_count, if_count); + ShowText(text); + socket.Close(); + } + +void CIpAdmEngine::HandleCommandL(TInt aCommand) + { + switch (aCommand) + { + case EIpAdmInterfaces: + ListInterfaces(4,_L("udp")); +// ListInterfaces(6,_L("udp6")); + break; + case EIpAdmRoutes: + ListRoutes(4, _L("udp")); +// ListRoutes(6, _L("udp6")); + break; + case EIpAdmAddRoutes: + AddRoutes(_L("udp")); + break; + default: + break; + } + } + + +// +// CIpAdmEngine::CheckResult +// Output success or fail message, returns the error code +// +TInt CIpAdmEngine::CheckResult(const TDesC &aText, TInt aResult) + { + if (aResult == KErrNone) + return KErrNone; + + TBuf<100> err; + CEikonEnv::Static()->GetErrorText(err, aResult); + + TBuf<200> str(aText); + str.AppendFormat(_L(" returned with [%s] "), err.PtrZ()); + iAppView->Write(str); + + return aResult; + } +// +// CIpAdmEngine::CheckResultL +// Output success or fail message, and Leave if the code is not +// KErrNone. +// +void CIpAdmEngine::CheckResultL(const TDesC &aText, TInt aResult) + { + if (CheckResult(aText, aResult) != KErrNone) + User::Leave(aResult); + } + +void CIpAdmEngine::ShowText(const TDesC &aText) + { + iAppView->Write(aText); + } +