--- /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 <eikenv.h>
+#include "ipadm.h"
+#include "engine.h"
+
+#include "uniload.h"
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <in_sock_internal.h>
+#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<TSoInetInterfaceInfo> 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<TSoInetRouteInfo> 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<TSoInetRouteInfo> 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<TSoInet6InterfaceInfo> 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<TSoInetIfQuery> opt1;
+ TPckgBuf<TSoInetIfQuery> 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);
+ }
+