networkprotocols/tcpipv4v6prt/src/iface.cpp
changeset 0 af10295192d8
child 5 1422c6cd3f0c
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     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 // iface.cpp - IPv6/IPv4 interface and route manager
       
    15 // Implementations of flows, routes and interfaces for IPv6.
       
    16 // CIp6Manager
       
    17 // |iInterfaceList 
       
    18 // /         iFlowList\    /       iRouteList\  |
       
    19 // V    iRoute           \ V    iInterface      \V
       
    20 // CIp6Flow ------------> CIp6Route -----------> CIp6Interface  ---> NIF
       
    21 // |iNext                  |iNext       iAddress/|iNext
       
    22 // |                       |         CIp6Address |
       
    23 // |                       |         (list) |    |
       
    24 // V                       V                     |
       
    25 // CIp6Flow               CIp6Route                 V
       
    26 // |                       |                  CIp6Interface
       
    27 // íAddress/|
       
    28 // CIp6Address
       
    29 // A sketch of the Interface state transitions from StartSending/Error/Send calls
       
    30 // and the resulting return values for StartSending (UP, READY). Not
       
    31 // shown, but NONE is returned when StartSending is called in READY
       
    32 // (unless address is changed, in which case UP is returned regardless
       
    33 // of previous state).
       
    34 // / Error( <0 )         / Error( <0 )      |
       
    35 // |                     |                   V
       
    36 // PENDING ------------> READY --------------> DOWN
       
    37 // StartSending   | ^  Error( <0 )      |
       
    38 // ( == UP)    | |                  /
       
    39 // Send| |( == READY)     /
       
    40 // return| |StartSending  /
       
    41 // V |            /
       
    42 // HOLD --------->
       
    43 // Error (<0)
       
    44 // Define WEAK_ES, if you don't want STRONG ES model for
       
    45 // the host.
       
    46 //
       
    47 
       
    48 
       
    49 
       
    50 /**
       
    51  @file iface.cpp
       
    52  @verbatim
       
    53  @endverbatim
       
    54  @verbatim
       
    55  @endverbatim
       
    56 */
       
    57 #undef WEAK_ES
       
    58 //#define WEAK_ES
       
    59 
       
    60 // Support for IPv6 DNS Configuration based on Router Advertisement
       
    61 
       
    62 
       
    63 #define SYMBIAN_NETWORKING_UPS
       
    64 
       
    65 //
       
    66 // In Epoc R6 nifman.h has been split, CNifIfBase definition has been moved
       
    67 // into <comms-infras/nifif.h>.
       
    68 //
       
    69 #include <e32hal.h>
       
    70 #include <e32math.h>
       
    71 #include <nifman.h>
       
    72 #include <comms-infras/nifif.h> // ..for CNifIfBase in Epoc R6 and later
       
    73 
       
    74 #include <in6_opt.h>
       
    75 #include <in_sock.h>
       
    76 #include "inet6log.h"
       
    77 #include "iface.h"
       
    78 #include <in6_if.h>     // IPv6 driver API specifications
       
    79 #include <icmp6_hdr.h>
       
    80 #include <in_chk.h>
       
    81 #include <ip6_hook.h>
       
    82 #include "in_flow.h"
       
    83 #include <timeout.h>
       
    84 #include <inet6err.h>
       
    85 #include "addr46.h"
       
    86 #ifdef ARP
       
    87 #include <arp_hdr.h>
       
    88 #endif
       
    89 
       
    90 #include <es_ini.h>
       
    91 
       
    92 #ifdef SYMBIAN_NETWORKING_UPS
       
    93 #include "in_trans.h"
       
    94 #endif
       
    95 
       
    96 #include "tcpip_ini.h"
       
    97 #include "networkinfo.h"
       
    98 #include <in6_event.h>
       
    99 #include <in6_dstcache.h>
       
   100 
       
   101 #include "in6_version.h"
       
   102 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
   103 #include <in_sock_internal.h>
       
   104 #include <in6_dstcache_internal.h>
       
   105 #endif
       
   106 
       
   107 
       
   108 // Temporay backward portability definition, until
       
   109 // KErrLinkConfigChanged is standard from some SDK
       
   110 // version forward. For now, if a special version
       
   111 // is installed, define LINK_CONFIG_CHANGED in MMP
       
   112 // file. -- msa
       
   113 #ifdef LINK_CONFIG_CHANGED
       
   114 #   include <agenterrors.h>
       
   115 #else
       
   116 #   define  KErrLinkConfigChanged (-3060)
       
   117 #endif
       
   118 
       
   119 #include <comms-infras/nifif_internal.h>
       
   120 #include <nifman_internal.h>
       
   121 
       
   122 //
       
   123 // DAEMON_USE_PROCESSES must be set in MMP file if required by SDK. It
       
   124 // determines whether daemons are to be run on threads or on real
       
   125 // processes. Only force here that processes are always used when
       
   126 // compiling for target device.
       
   127 //
       
   128 
       
   129 /**
       
   130 * The basic timer unit.
       
   131 *
       
   132 * To enable compile time optimization, the unit is
       
   133 * defined as preprocessor constant. The value indicates
       
   134 * the fraction of the second to be used as a basic unit
       
   135 * of the timer. This can be from 1 to 1000000 (from 1
       
   136 * second to 1 microsecond).
       
   137 */
       
   138 #define TIMER_UNIT 100
       
   139 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
   140 const TInt KRDNSSGranularity = 4; // Shall hold not more than 4 RDNSS Address
       
   141 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
   142 
       
   143 //
       
   144 //lint -save -e708 stupid lint info
       
   145 /**
       
   146 * @name Well known multicast and other addresses of the neighbour discovery.
       
   147 *
       
   148 * @{
       
   149 */
       
   150 /** Multicast to all receivers on this node. */
       
   151 const TIp6Addr KInet6AddrNodeLocal  = {{{0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,1}}};
       
   152 /** Multicast to all hosts on the link. */
       
   153 const TIp6Addr KInet6AddrAllNodes   = {{{0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1}}};
       
   154 /** Multicast to all routers on the link  */
       
   155 const TIp6Addr KInet6AddrAllRouters = {{{0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,2}}};
       
   156 /** @} */
       
   157 //lint -restore
       
   158 
       
   159 // speed optimisations
       
   160 #ifdef __ARMCC__
       
   161 #pragma push
       
   162 #pragma arm
       
   163 #endif
       
   164 
       
   165 class TInetNdConfig
       
   166     /**
       
   167     * Neighbor Discovery (RFC-2461) Protocol Constants.
       
   168     *
       
   169     * The constants are defined as members of TInetNdConfig, because
       
   170     * in future it is possible that a link layer specific variations
       
   171     * will be defined and some control option is provided to access
       
   172     * them.
       
   173     *
       
   174     * (with some extras from RFC-2462).
       
   175     */
       
   176     {
       
   177 public:
       
   178     // - router constants
       
   179     TUint iMaxInitialRtrAdvertInterval; //< seconds
       
   180     TUint iMaxInitialRtrAdvertisements; //< transmissions
       
   181     TUint iMaxFinalRtrAdvertisements;   //< transmissions
       
   182     TUint iMinDelayBetweenRas;          //< seconds
       
   183     // - host constants
       
   184     TUint iMaxRtrSolicitationDelay;     //< seconds
       
   185     TUint iRtrSolicitationInterval;     //< seconds
       
   186     TUint iMaxRouterSolicitations;      //< transmissions
       
   187     // - node constants
       
   188     TUint iMaxMulticastSolicit;         //< transmissions
       
   189     TUint iMaxUnicastSolicit;           //< transmissions
       
   190     TUint iMaxAnycastDelayTime;         //< seconds
       
   191     TUint iMaxNeighborAdvertisement;    //< transmissions
       
   192     TUint iReachableTime;               //< milliseconds
       
   193     TUint iRetransTimer;                //< milliseconds
       
   194     TUint iDelayFirstProbeTime;         //< seconds
       
   195     TReal iMinRandomFactor;             //
       
   196     TReal iMaxRandomFactor;
       
   197 
       
   198     // RFC-2462 additions
       
   199     TUint iDupAddrDetectTransmits;      //< transmissions
       
   200 
       
   201     // IPv4 (and IPv6?) (draft-ietf-zeroconf-ipv4-linklocal-05)
       
   202     TUint iMaxAddrRegenerations;        //< addresses generated
       
   203     TUint iDupAddrDefendTime;           //< seconds
       
   204 
       
   205     // IPv4 Linklocal Address specifications (draft-ietf-zeroconf-ipv4-linklocal-05)
       
   206     TUint iIPv4DupAddrDetectTransmits;  //< transmissions
       
   207     TUint iIPv4DupAddrAnnouncements;    //< announcements
       
   208     TUint iIPv4RetransTimer;            //< seconds (for Dup and Announce)
       
   209 
       
   210     // Router Reachability probing (draft-ietf-ipv6-router-selection-02.txt)
       
   211     TUint iRateLimitProbingTime;        //< seconds
       
   212     };
       
   213 
       
   214 /** The current default values (from RFC-2461). */
       
   215 const TInetNdConfig KInetNdConfig =
       
   216     {
       
   217     //- router constants
       
   218     /* MaxInitialRtrAdvertInterval */   16, // seconds
       
   219     /* MaxInitialRtrAdvertisements */   3,  // transmissions
       
   220     /* MaxFinalRtrAdvertisements */     3,  // transmissions
       
   221     /* MinDelayBetweenRas */            3,  // seconds
       
   222     // - host constants
       
   223     /* MaxRtrSolicitationDelay */       1,  // second
       
   224     /* RtrSolicitationInterval */       4,  // seconds
       
   225     /* MaxRouterSolicitations */        3,  // transmissions
       
   226     // - node constants
       
   227     /* MaxMulticastSolicit */           3,  // transmissions
       
   228     /* MaxUnicastSolicit */             3,  // transmissions
       
   229     /* MaxAnycastDelayTime */           1,  // second
       
   230     /* MaxNeighborAdvertisement */      3,  // transmissions
       
   231     /* ReachableTime */             30000,  // milliseconds
       
   232     /* RetransTimer */               1000,  // milliseconds
       
   233     /* DelayFirstProbeTime */           5,  // seconds
       
   234     /* MinRandomFactor */               0.5,
       
   235     /* MaxRandomFactor */               1.5,
       
   236 
       
   237     // - RFC-2462 additions
       
   238     /* DupAddrDetectTransmits */        1,  // transmissions
       
   239 
       
   240     // IPv4 (and IPv6?) (draft-ietf-zeroconf-ipv4-linklocal-05)
       
   241     /* MaxAddrRegenerations */          10, // max addresses generated
       
   242     /* DupAddrDefendTime */             10, // seconds
       
   243 
       
   244     // IPv4 Linklocal Address specifications (draft-ietf-zeroconf-ipv4-linklocal-07)
       
   245     /* IPv4DupAddrDetectTransmits */    3,  // transmissions
       
   246     /* IPv4DupAddrAnnouncements */      2,  // announcements
       
   247     /* IPv4RetransTimer */              1,  // seconds (for Dup and Announce)
       
   248 
       
   249     // Router Reachability probing (draft-ietf-ipv6-router-selection-02.txt)
       
   250     /* iRateLimitProbingTime */         60  // seconds
       
   251     };
       
   252 
       
   253 
       
   254 /**
       
   255 * @name Route Preference constants
       
   256 *
       
   257 * @{
       
   258 */
       
   259 /** Route preference values. */
       
   260 enum TRoutePreference
       
   261     {
       
   262     ERoutePreference_MEDIUM = 0,    //< Prf = 0
       
   263     ERoutePreference_HIGH   = 1,    //< Prf = 1
       
   264     ERoutePreference_INVALID= 2,    //< Prf = -0
       
   265     ERoutePreference_LOW    = 3     //< Prt = -1
       
   266     };
       
   267 
       
   268 /** Translate TRoutePrefence value to route metric. */
       
   269 const TInt KPreferenceMetric[4] =
       
   270     {
       
   271     1,  // 0 (medium) and the default for metric in all created routes.
       
   272     0,  // 1 (high)
       
   273     0,  // 2 (invalid)
       
   274     2,  // 3 (low)
       
   275     };
       
   276 /** @} */
       
   277 
       
   278 //
       
   279 // TIcmpNdHeader
       
   280 // *************
       
   281 class TIcmpNdHeader
       
   282     /** 
       
   283     * Collection of the ICMP Messages relating to the
       
   284     * Neigbor Discovery (RFC 2461).
       
   285     */
       
   286     {
       
   287 public:
       
   288     //
       
   289     // Basic
       
   290     //
       
   291     inline static TInt MinHeaderLength() {return 8; }
       
   292     inline static TInt MaxHeaderLength() {return 40; }  // Not much useful
       
   293 
       
   294     union
       
   295         {
       
   296         TInet6HeaderICMP iIcmp;
       
   297         TInet6HeaderICMP_RouterSol iRS;
       
   298         TInet6HeaderICMP_RouterAdv iRA;     
       
   299         TInet6HeaderICMP_NeighborSol iNS;
       
   300         TInet6HeaderICMP_NeighborAdv iNA;
       
   301         TInet6HeaderICMP_Redirect iRD;
       
   302         };
       
   303     };
       
   304 //
       
   305 // TIcmpNdOption
       
   306 // *************
       
   307 class TIcmpNdOption
       
   308     /**
       
   309     * Collection of the ICMP options relating to the
       
   310     * Neighbor Disovery (RFC 2461).
       
   311     */
       
   312     {
       
   313 public:
       
   314     inline static TInt MinHeaderLength() {return 8; }
       
   315     inline static TInt MaxHeaderLength() {return 40; }  // Not much useful
       
   316 
       
   317     union
       
   318         {
       
   319         TInet6OptionICMP_LinkLayer iLink;
       
   320         TInet6OptionICMP_Prefix iPrefix;
       
   321         TInet6OptionICMP_Mtu iMtu;
       
   322 #if 1
       
   323         // Experimental: draft-ietf-ipv6-router-selection-02.txt
       
   324         // Default Router Preferences, More-Specific Routes, and Load Sharing
       
   325         TInet6OptionICMP_RouteInformation iRouteInformation;
       
   326 #endif
       
   327 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
   328         // IPv6 DNS Configuration based on Router Advertisement: RFC-5006
       
   329         TInet6OptionICMP_DnsInformationV1 iDnsInformation;
       
   330 #else
       
   331         // Experimental: draft-jeong-dnsop-ipv6-discovery-03.txt
       
   332         // IPv6 DNS Configuration based on Router Advertisement
       
   333         TInet6OptionICMP_DnsInformation iDnsInformation;
       
   334 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
   335         };
       
   336     };
       
   337 
       
   338 // TRouteAddress
       
   339 // *************
       
   340 class TRouteAddress
       
   341     /**
       
   342     * Internal class to hold an address.
       
   343     *
       
   344     * Internal help class which can hold any address of the TSockAddr, but
       
   345     * does not inlude the port field or TBuf8 descriptor. Mainly required
       
   346     * to get rid of the TSockAddr constructor, which prevents it's use
       
   347     * inside union structure.
       
   348     *
       
   349     * If family is KAfInet6, then address is IPv6 or IPv4 address; otherwise
       
   350     * the address is assumed to be a link layer address.
       
   351     *
       
   352     * Only a raw addresses are handled. Port, Scope Id and Flow label are
       
   353     * not included.
       
   354     */
       
   355     {
       
   356 public:
       
   357     inline TUint Family() const { return iFamily; }
       
   358     inline TPtrC8 Address() const
       
   359         /**
       
   360         * Get the raw address bytes.
       
   361         * @return descriptor for the raw address bytes.
       
   362         */
       
   363         {
       
   364         return TPtrC8(iBuf, iLength);
       
   365         }
       
   366     inline const TIp6Addr &Ip6Address() const
       
   367         /**
       
   368         * Get the raw IPv6 address.
       
   369         *
       
   370         * @return IPv6 address.
       
   371         */
       
   372         {
       
   373         return (TIp6Addr &)iBuf[0];
       
   374         }
       
   375     void SetAddress(const TIp6Addr &aAddr);
       
   376     void SetAddress(const TSockAddr &aAddr);
       
   377     void GetAddress(TSockAddr &aAddr) const;
       
   378     TBool Match(const TSockAddr& aAddr) const;
       
   379 private:
       
   380     TUint iFamily;      //< Address family (0 = KAFUnspec)
       
   381     TUint iLength;      //< The length of the stored address
       
   382     // ..and enough space for any possible address used in TSockAddr
       
   383     TUint8 iBuf[KMaxSockAddrSize];//< Address bytes.
       
   384     };
       
   385 
       
   386 void TRouteAddress::SetAddress(const TIp6Addr &aAddr)
       
   387     /**
       
   388     * Set address from raw IPv6 address.
       
   389     *
       
   390     * @param aAddr The Address.
       
   391     */
       
   392     {
       
   393     ASSERT(sizeof(iBuf) >= sizeof(TIp6Addr));
       
   394     *(TIp6Addr *)iBuf = aAddr;
       
   395     iFamily = KAfInet6;
       
   396     iLength = sizeof(TIp6Addr);
       
   397     }
       
   398 
       
   399 void TRouteAddress::SetAddress(const TSockAddr &aAddr)
       
   400     /**
       
   401     * Set address from a TSockAddr.
       
   402     *
       
   403     * @param aAddr The Address
       
   404     */
       
   405     {
       
   406     TPtr8 ptr(iBuf, sizeof(iBuf));
       
   407     ptr = TLinkAddr::Cast(aAddr).Address();
       
   408     
       
   409     // Unfortunately, IPv6 addresses have to be treated specially,
       
   410     // the iLength must reflect the plain IPv6 address, and not the
       
   411     // TInetAddr user length. Otherwise, setting IPv6
       
   412     // from TInetAddr and TIp6Addr will not result matching
       
   413     // entries... (icky! Perhaps needs some other fix..)
       
   414     // Someone is bound to trip over this!! -- msa
       
   415     // [...to use TInetAddr Userlen() is *NOT* a solution. Comparisons
       
   416     // should only involve IPv6 address and not include scope/flow etc.]
       
   417     iFamily = aAddr.Family();
       
   418     iLength = iFamily == KAfInet6 ? sizeof(TIp6Addr) : ptr.Length();
       
   419     }
       
   420 
       
   421 void TRouteAddress::GetAddress(TSockAddr &aAddr) const
       
   422     /**
       
   423     * Gets stored address into TSockAddr
       
   424     *
       
   425     * @retval aAddr The address.
       
   426     */
       
   427     {
       
   428     // Have to undo the trickery in SetAddress (yet another yechh!) -- msa
       
   429     if (iFamily == KAfInet6)
       
   430         TInetAddr::Cast(aAddr).SetAddress(Ip6Address());
       
   431     else
       
   432         {
       
   433         aAddr.SetFamily(iFamily);
       
   434         TLinkAddr::Cast(aAddr).SetAddress(Address());
       
   435         }
       
   436     }
       
   437 
       
   438 TBool TRouteAddress::Match(const TSockAddr& aAddr) const
       
   439     /**
       
   440     * Tests if the stored address matches another address.
       
   441     *
       
   442     * @param aAddr Another address.
       
   443     *
       
   444     * @return ETrue, if addresses are same; otherwise EFalse.
       
   445     */
       
   446     {
       
   447     if (iFamily != aAddr.Family())
       
   448         return FALSE;
       
   449     if (iFamily == KAFUnspec)
       
   450         return TRUE;
       
   451     if (iFamily == KAfInet6)
       
   452         return Ip6Address().IsEqual(TInetAddr::Cast(aAddr).Ip6Address());
       
   453     else
       
   454         return Address() == TLinkAddr::Cast(aAddr).Address();
       
   455     }
       
   456 
       
   457 
       
   458 // TSolicitedNodeAddr
       
   459 // *******************
       
   460 class TSolicitedNodeAddr : public TIp6Addr
       
   461     /**
       
   462     * Generates Solicited Node Multicast address.
       
   463     *
       
   464     * An class whose sole purpose is to construct an intialized
       
   465     * TIp6Address, which holds a solicited node multicast address
       
   466     */
       
   467     {
       
   468 public:
       
   469     TSolicitedNodeAddr(const TIp6Addr &aAddress)
       
   470         {
       
   471         const union { TUint8 a[4]; TUint32 b; } mc_node = {{0xff, 0x02, 0, 0}};
       
   472         const union {TUint8 a[4]; TUint32 b;} one = { {0, 0, 0, 1} };
       
   473         const union {TUint8 a[4]; TUint32 b;} ff = { {0xff, 0, 0, 0} };
       
   474 
       
   475         u.iAddr32[0] = mc_node.b;
       
   476         u.iAddr32[1] = 0;
       
   477         u.iAddr32[2] = one.b;
       
   478         u.iAddr32[3] = ff.b | aAddress.u.iAddr32[3];
       
   479         }
       
   480     };
       
   481 
       
   482 // Lifetime definitions
       
   483 // ********************
       
   484 // (values are seconds)
       
   485 //
       
   486 typedef TUint32 TLifetime;
       
   487 const TUint32 KLifetimeForever = KMaxTUint32;
       
   488 
       
   489 //
       
   490 // The implementations of
       
   491 //      CIp6Interface
       
   492 //      CIp6Route
       
   493 //      CIp6Flow
       
   494 //      CIp6NifUser
       
   495 //      CIp6Daemon
       
   496 // are internal to this module and thus the class declaration do not need to
       
   497 // be visible to any outsider.
       
   498 //
       
   499 // *NOTE*
       
   500 //      The public/private/protected and friend designations are total mess
       
   501 //      and should be cleaned up, if nothing else, then make all public, as
       
   502 //      these classes cross reference each other too much... -- msa
       
   503 //
       
   504 class CIp6Flow;
       
   505 class CIp6Route;
       
   506 class CIp6Interface;
       
   507 class CIp6NifUser;
       
   508 class CIp6Daemon;
       
   509 class MNifIfUser;
       
   510 class CNifIfBase;
       
   511 class MTimeoutManager;
       
   512 
       
   513 //
       
   514 //  CIp6Manager
       
   515 //  ***********
       
   516 //
       
   517 class CIp6Manager : public CIfManager, public MNetworkInfo
       
   518     , public MProvdSecurityChecker
       
   519     {
       
   520     // ... lots of "friends", look into this later -- msa
       
   521     friend class CIp6Flow;
       
   522     friend class CIp6Interface;
       
   523     friend class CIp6Route;
       
   524     friend class CIp6NifUser;
       
   525     friend class CIp6ManagerTimeoutLinkage;
       
   526     //
       
   527     // Construct and InitL are only used from CIfManager::NewL()
       
   528     //
       
   529     friend class CIfManager;
       
   530 
       
   531     CIp6Manager();
       
   532     void InitL();
       
   533     //
       
   534     virtual ~CIp6Manager();
       
   535     TBool LoadConfigurationFile();
       
   536 public:
       
   537     // Access to the configuration file (tcpip.ini)
       
   538     TBool FindVar(const TDesC &aSection,const TDesC &aVarName,TPtrC &aResult);
       
   539     TBool FindVar(const TDesC &aSection,const TDesC &aVarName,TInt &aResult);
       
   540     //
       
   541     // Implement virtual methods required by the CIfManager
       
   542     //
       
   543     inline TInt FlowCount() { return iFlows; }
       
   544     inline TInt UserCount() { return iUsers; }
       
   545     inline TInt NifCount() { return iNifCount; }
       
   546 
       
   547     virtual void AddRouteL(const TIp6Addr &aAddr, TInt aPrefix, const TDesC &aName,
       
   548         TUint aFlags = KRouteAdd_ONLINK, const TSockAddr *const aGateway = NULL, const TUint32 *const aLifetime = NULL);
       
   549     virtual TInt CheckRoute(const TIp6Addr &aAddr, const TUint32 aScopeid, TIp6Addr &aSrc) const; 
       
   550     virtual TUint32 LocalScope(const TIp6Addr &aAddr, const TUint32 aLock, const TScopeType aLockType) const;
       
   551     virtual TUint32 RemoteScope(const TIp6Addr &aAddr, const TUint32 aLock, const TScopeType aLockType) const;
       
   552     virtual TUint32 IsForMeAddress(const TIp6Addr &aAddr, const TUint32 aInterfaceIndex) const;
       
   553     virtual TInt IsForMePacket(RMBufRecvInfo &aInfo) const;
       
   554 
       
   555     virtual const MInterface* Interface(const CNifIfBase *const aIf) const;
       
   556     virtual const MInterface* Interface(const TDesC &aName) const;
       
   557     virtual const MInterface* Interface(const TUint32 aInterfaceIndex) const;
       
   558 
       
   559     // Get* methods are new versions of InterfaceInfo and RouteInfo.
       
   560     // Instead of iterating through by returning one
       
   561     // entry per each call, Get* methods return an array of entries in aOption buffer when
       
   562     // returning. I.e., Get* methods return an atomic snapshot of the current status.
       
   563     virtual TUint InterfaceInfo(TUint aIndex, TSoInetInterfaceInfo &aInfo) const;
       
   564     virtual TUint RouteInfo(TUint aIndex, TSoInetRouteInfo &aInfo) const;
       
   565 
       
   566     // Doxy descriptions for the Get*() methods can be found in MNetworkInfo definition.
       
   567     // These implement MNetworkInfo, thus Doxygen shows the same comments here
       
   568     virtual TInt GetInterfaces(TDes8& aOption) const;
       
   569     virtual TInt GetAddresses(TDes8& aOption) const;
       
   570     virtual TInt GetRoutes(TDes8& aOption) const;
       
   571 
       
   572       // Options processing
       
   573     virtual TInt GetOption(TUint aLevel, TUint aName, TDes8 &aOption) const;
       
   574     virtual TInt SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption);
       
   575     TInt CheckPolicy(const TSecurityPolicy& /*aPolicy*/, const char */*aDiagnostic*/) { return KErrNone; }
       
   576     virtual TInt GetOption(TUint aLevel, TUint aName, TDes8 &aOption, MProvdSecurityChecker &aChecker) const;
       
   577     virtual TInt SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption, MProvdSecurityChecker &aChecker);
       
   578 
       
   579     // "Users" housekeeping. 
       
   580     virtual void IncUsers();
       
   581     virtual void DecUsers();
       
   582     //
       
   583     virtual TInt PacketAccepted(const TUint32 aInterfaceIndex);
       
   584 
       
   585     // Flows
       
   586     virtual CFlowContext *NewFlowL(const void *aOwner, MFlowManager *aManager, TUint aProtocol);
       
   587     virtual CFlowContext *NewFlowL(const void *aOwner, MFlowManager *aManager, CFlowContext &aFlow);
       
   588     virtual TInt SetChanged() const;
       
   589     //
       
   590     //
       
   591     virtual TInt StartSending(CNifIfBase *aIface);
       
   592     virtual TInt Error(TInt aError, CNifIfBase *aIface);
       
   593     //
       
   594     // Protocol registering (iNifUsers list)
       
   595     //
       
   596     virtual MNifIfUser *Register(MNetworkServiceExtension *aProtocol);  // Makes protocol visible to interfaces
       
   597     virtual void Unregister(MNetworkServiceExtension *aProtocol);   // Removes protocol (called from protocol destructor)
       
   598     // ICMP stuff
       
   599     TInt IcmpError(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo);
       
   600     TInt IcmpHandler(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo);
       
   601 
       
   602 #ifdef ARP
       
   603     virtual TInt ArpHandler(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo);
       
   604 #endif
       
   605     //
       
   606     // Accessing the main components uniformly independent of the class
       
   607     // (when linkages between classes change, just change these to reflect
       
   608     // the change, and the rest of the code should work unchanged)
       
   609     //
       
   610     inline CIp6Manager &Interfacer() { return *this; };
       
   611 
       
   612     TInt GetDstCachePathMtu(const TIp6Addr& aDstAddress, TUint32 aScopeId) const;
       
   613     void *GetApiL(const TDesC8& aApiName, TUint* aVersion);
       
   614     
       
   615     // Returns the event manager instance used by the stack
       
   616     inline MEventService *EventManager() const { return iEventManager; }
       
   617 
       
   618     // Wrap a packet into ICMP error reply
       
   619     void IcmpSend(RMBufChain &aPacket, const TIcmpTypeCode aIcmp, const TUint32 aParameter = 0, const TInt aMC = 0);
       
   620 
       
   621 private:
       
   622 #   ifdef WEAK_ES
       
   623     TUint32 IsForMe(const TIp6Addr &aAddr, const CIp6Interface *const aSrcIf,
       
   624         const TUint32 aScopeId, const TScopeType aType) const;
       
   625 #   else
       
   626     TUint32 IsForMe(const TIp6Addr &aAddr, const CIp6Interface *const aSrcIf) const;
       
   627 #   endif
       
   628     //
       
   629     //
       
   630     CIp6Interface *FindInterface(const CNifIfBase *aInterface) const;
       
   631     CIp6Interface *FindInterface(const TAny *aId) const;
       
   632     CIp6Interface *FindInterface(const TInetAddr &aAddr) const;
       
   633     CIp6Interface *FindInterface(const TUint32 aIndex) const;
       
   634     CIp6Interface *FindInterface(const TDesC &aName) const;
       
   635     CIp6Interface *FindInterface(const TUint32 aIndex, const TScopeType aLevel) const;
       
   636     //
       
   637     // Internal Route manipulation
       
   638     //
       
   639     CIp6Route *FindRoute
       
   640         (const TIp6Addr &aDst, const TUint32 aDstId, const TUint aDstType,
       
   641          const TIp6Addr &aSrc = KInet6AddrNone, const TUint32 aSrcId = 0) const;
       
   642     void ProbeDestination
       
   643         (const TIp6Addr &aDst, const TUint32 aDstId, const TUint aDstType,
       
   644          const TIp6Addr &aSrc = KInet6AddrNone, const TUint32 aSrcId = 0) const;
       
   645     //
       
   646     // "HoldingRoute()" returns the dummy "default" route entry that gets all
       
   647     // the flows that wait for interface setup (like dialup).
       
   648     //
       
   649     CIp6Route *HoldingRoute() const { return iHoldingRoute; }
       
   650     //
       
   651     // Moving flow()s to holding route
       
   652     //
       
   653     void MoveToHolding(CIp6Flow &aFlow) const;  // Move the specific aFlow
       
   654     void MoveToHolding(CIp6Route &aRoute) const;    // Move all flows from aRoute
       
   655 
       
   656     //
       
   657     // ScanHoldings() scans the flows in the special holding route and
       
   658     // checks if any of them could now be assigned to a real route (and
       
   659     // does so, if yes).
       
   660     void ScanHoldings();
       
   661     //
       
   662     // Get interface by name (and create a new entry, if not found)
       
   663     //
       
   664     CIp6Interface *GetInterfaceByNameL(const TDesC &aName);
       
   665     //
       
   666     // Unconditional removal of the interface
       
   667     //
       
   668     void RemoveInterface(CIp6Interface *aIf);
       
   669     //
       
   670     // Modify Inet Interface information (SetOption part!)
       
   671     //
       
   672     TInt InetInterfaceOption(TUint aName, const TSoInet6InterfaceInfo &aInfo);
       
   673     //
       
   674     // Query Interface Information
       
   675     //
       
   676     TInt InterfaceQueryOption(TUint aName, TSoInetIfQuery &aQuery, const TInt aLength) const;
       
   677     //
       
   678     // A gateway from Set/Get Option to interface
       
   679     //
       
   680     TInt InterfaceOption(TUint aLevel, TUint aName, TDes8 &aOption) const;
       
   681 
       
   682     // Called when SetOption for KSoIpv4LinkLocal has been issued.
       
   683     TInt SetIpv4LinkLocalOption(const TSoInetIpv4LinkLocalInfo &aOption);
       
   684     
       
   685     //
       
   686     // Multicast Join/Leave Group processing
       
   687     //
       
   688     TInt MulticastOption(TUint aName, const TIp6Mreq &aRequest);
       
   689     //
       
   690     // Automatic Daemon control (start/stop)
       
   691     //
       
   692     void StartDaemons();
       
   693     void StopDaemons();
       
   694     void Timeout(const TTime &aStamp);  // Timer expiration event handler
       
   695     static TUint TimerUnits(const TUint aDelay, const TUint aUnit = 1);
       
   696     void SetTimer(RTimeout &aHandle, TUint32 aDelay);
       
   697 
       
   698     inline void SetTimerWithUnits(RTimeout &aHandle, TUint32 aDelay)
       
   699         {
       
   700         iTimeoutManager->Set(aHandle, aDelay);
       
   701         }
       
   702 
       
   703     //
       
   704     // Set/reset a timer event on the current object
       
   705     //
       
   706     inline void SetTimer(TUint32 aDelay) { SetTimer(iTimeout, aDelay); }
       
   707     // CancelTimer/IsTimerActive are just syntactic sugar, because
       
   708     // of the SetTimer: if one uses SetTimer and hides iTimeout, then
       
   709     // all uses of iTimeout should be "hidden" too!
       
   710     inline void CancelTimer() { iTimeout.Cancel(); }
       
   711     inline TBool IsTimerActive() { return iTimeout.IsActive(); }
       
   712 
       
   713     //
       
   714     // Get tcpip.ini values
       
   715     //
       
   716     TInt GetIniValue(const TDesC &aSection, const TDesC &aName, TInt aDefault = 0, TInt aMin = 0, TInt aMax = 1);
       
   717 
       
   718     CIp6Route *iHoldingRoute;           //< Always Exists! The place for pending flows
       
   719     CIp6Interface *iInterfaceList;      //< All interfaces
       
   720     CIp6Daemon *iDaemons;               //< Daemons created in InitL
       
   721     TInt iLinkLocalTTL;                 //< Default TTL/Hoplimit for unicast link local destinations
       
   722     TUint8 iMaxTTL;                     //< Default TTL/Hoplimit
       
   723     TUint8 iRA_OptRoute;                //< Assigned value for KInet6OptionICMP_RouteInformation (until fixed by IANA)
       
   724 #ifndef SYMBIAN_TCPIPDHCP_UPDATE     
       
   725     TUint8 iRA_OptDns;                  //< Assigned value for KInet6OptionICMP_DnsInformation (until fixed by IANA)
       
   726 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
   727     // Default value for the flow iNoInterfaceError flag
       
   728     TUint iNoInterfaceError:1;
       
   729     // Default value for the flow iKeepInterfaceUp flag
       
   730     TUint iKeepInterfaceUp:1;
       
   731 
       
   732     // Configure IPv4 link local addresses, if non-zero.
       
   733     // Determines the default interface-specific setting in CIp6Interface
       
   734     // (see there for usable values).
       
   735     TUint iIpv4Linklocal:3;
       
   736 
       
   737     // Disable "ID defense mode", if non-zero
       
   738     TUint iNoDefendId:1;
       
   739     // Enable ND probing for addresses for which there is no route
       
   740     TUint iProbeAddress:1;
       
   741 
       
   742     // = 1, if holding queue should be scanned
       
   743     TUint iScanHolding:1;
       
   744     /**
       
   745     // Number of seconds to wait, before killing the daemons (DND etc)
       
   746     // after the last *counted* user (SAP, NIF) exits.
       
   747     */
       
   748     TUint iShutdownDelay;
       
   749     // A maximum timelimit for holding flows (seconds).
       
   750     TUint iMaxHoldingTime;
       
   751     /**
       
   752     // iMaxTickInterval is precomputed at initialize and holds the
       
   753     // longest time interval in seconds that can be expressed
       
   754     // with tick counts (when used as time stamps and compared)
       
   755     // (= number of seconds corresponding KMaxTInt ticks)
       
   756     */
       
   757     TUint iMaxTickInterval;
       
   758     // for Random sequence...
       
   759     TInt64 iSeed;
       
   760     //
       
   761     // iNifUser array is filled at init with
       
   762     // allocated objects of CIp6NifUser. A Register()
       
   763     // call from a protocol will fill in itself to
       
   764     // the appropriate slot (overriding any previous
       
   765     // register).
       
   766     //
       
   767     // All this because I don't know for sure what NIF wants,
       
   768     // but it does appear to assume that there is one-to-one
       
   769     // mapping between a protocol instance and MIfNifUser.
       
   770     // -- msa
       
   771     enum
       
   772         {
       
   773         E_IPv4 = 0,     // for a protocol supporting KAfInet
       
   774         E_IPv6 = 1,     // for a protocol supporting KAfInet6
       
   775         E_IPmax
       
   776         };
       
   777     CIp6NifUser *iNifUser[E_IPmax];
       
   778 
       
   779     TInt iUsers;                        //< Count of active users
       
   780     TInt iNifCount;                     //< Count of NIF references
       
   781     TInt iFlows;                        //< Count of Flow contexts
       
   782     //
       
   783     TUint iInterfaceIndex;              //< Last assigned interface index (or zero)
       
   784     TUint iRouteIndex;                  //< Last assigned route index (or zero)
       
   785     MTimeoutManager *iTimeoutManager;   //< Provide Timer Services for the Interface Manager
       
   786     CESockIniData *iConfig;             //< Configuration data
       
   787     TInt iConfigErr;                    //< Non-zero, if configuration file is not available
       
   788 
       
   789     MEventService *iEventManager;       //< For providing interface and route events to the plugins.
       
   790     MDestinationCache *iDestinationCache;  //< Destination cache (for transport protocol params).
       
   791     
       
   792 public: // GCC doesn't compile Linkage, if this is private! -- msa
       
   793     RTimeout iTimeout;                  //< Hook to the timer service (MTimeoutManager)
       
   794     };
       
   795 
       
   796 //
       
   797 //  CIp6ManagerTimeoutLinkage
       
   798 //  *************************
       
   799 //  *NOTE*
       
   800 //      This kludgery is all static and compile time, and only used in the constructor
       
   801 //      of CIp6Interface.
       
   802 //
       
   803 
       
   804 // This ungainly manoevure is forced on us because the offset is not evaluated early enough by GCC3.4 to be
       
   805 // passed as a template parameter
       
   806 #if defined(__X86GCC__) || defined(__GCCE__)
       
   807 #define KIp6ManagerTimeoutOffset 104
       
   808 __ASSERT_COMPILE(KIp6ManagerTimeoutOffset == _FOFF(CIp6Manager, iTimeout));
       
   809 #else
       
   810 #define KIp6ManagerTimeoutOffset _FOFF(CIp6Manager, iTimeout)
       
   811 #endif
       
   812 
       
   813 class CIp6ManagerTimeoutLinkage : public TimeoutLinkage<CIp6Manager, KIp6ManagerTimeoutOffset>
       
   814     /**
       
   815     * Glue to bind timeout callback from the timeout manager into Timeout() call
       
   816     * on the CIp6Route
       
   817     */
       
   818     {
       
   819 public:
       
   820     static void Timeout(RTimeout &aLink, const TTime &aNow, TAny * /*aPtr*/)
       
   821         {
       
   822         LOG(Log::Printf(_L("<>\tCIp6Manager Timeout")));
       
   823         Object(aLink)->Timeout(aNow);
       
   824         }
       
   825     };
       
   826 
       
   827 //
       
   828 //  CIp6NifUser
       
   829 //  ***********
       
   830 //
       
   831 #ifdef _LOG
       
   832 _LIT(KIPv4, "IPv4");
       
   833 _LIT(KIPv6, "IPv6");
       
   834 #endif
       
   835 
       
   836 class CIp6NifUser : public CBase, public MNifIfUser
       
   837     {
       
   838     friend class CIp6Manager;
       
   839     friend class CIp6Interface;
       
   840     friend class CIp6Flow;
       
   841     friend class CIp6Route;
       
   842     CIp6NifUser(CIp6Manager &aManager, TBool aIPv4) : iManager(aManager), iIPv4(aIPv4) {}
       
   843     inline TBool IsIPv4() const {return iIPv4; }
       
   844 #ifdef _LOG
       
   845     const TDesC &LogName() const { return IsIPv4() ? KIPv4() : KIPv6(); }
       
   846 #endif
       
   847 public:
       
   848     //
       
   849     // Interface interface
       
   850     //
       
   851     void IfUserBindFailure(TInt aResult, TAny* aId);
       
   852     void IfUserNewInterfaceL(CNifIfBase* aIf, TAny* aId);
       
   853     void IfUserInterfaceDown(TInt aResult, CNifIfBase* aIf);
       
   854     void IfUserOpenNetworkLayer();
       
   855     void IfUserCloseNetworkLayer();
       
   856     CProtocolBase* IfUserProtocol();
       
   857     TBool IfUserIsNetworkLayerActive();
       
   858     TBool IfUserIsNetworkLayerActive(CNifIfBase *);
       
   859     //
       
   860     // Accessing the main components uniformly independent of the class
       
   861     // (when linkages between classes change, just change these to reflect
       
   862     // the change, and the rest of the code should work unchanged)
       
   863     //
       
   864     inline CIp6Manager &Interfacer() const { return iManager; };
       
   865 private:
       
   866     CIp6Manager &iManager;
       
   867     const TBool iIPv4;      // True for IPv4, False otherwise
       
   868     MNetworkServiceExtension *iNetwork;
       
   869     };
       
   870 
       
   871 
       
   872 // ***************
       
   873 // TIp6AddressInfo
       
   874 // ***************
       
   875 //
       
   876 class CIp6Address;
       
   877 class TIp6AddressInfo
       
   878     {
       
   879 public:
       
   880     // Match returns TRUE, if aAddr matches the ID/hostnumber.
       
   881     TBool Match(const TIp6Addr &aAddr) const;
       
   882     
       
   883     // Match returns TRUE if aAddr ID matches exactly (prefix is
       
   884     // not used to mask address bits).
       
   885     TBool MatchExactly(const TIp6Addr &aAddr) const;
       
   886 
       
   887     CIp6Address *iNext;
       
   888     /**
       
   889     // iId and iPrefix define the ID/hostnumber portion of
       
   890     // the address, aligned to end of the iId field.
       
   891     //
       
   892     // iPrefix is *usually* the length of the prefix to be
       
   893     // used with this id. Technically, iPrefix is the number
       
   894     // of bits in the iId, that DO NOT BELONG to the stored id.
       
   895     // The legal values are [0..128]. *Note* Storing address
       
   896     // with iPrefix=128 will make that id part match any
       
   897     // address (id length == 0!) -- careful with it!
       
   898     //
       
   899     // This is designed for IPv6 addresses, but the processing
       
   900     // is "tweaked" so that the same code works also for IPv4
       
   901     // as follows:
       
   902     //
       
   903     // @li IPv4 loopback net (127.x.x.x) is coded as
       
   904     //   route = ELoopback, 127.0.0.0/8, address = ::/128
       
   905     //   => Address match depends only on ELoopback prefix
       
   906     //
       
   907     // @li IPv4 address
       
   908     //   route = ELoopback, ::ffff:ipv4/128,
       
   909     //   address = ::ffff:ipv4/0. IPv4 is treated as single
       
   910     //   unit (not split into prefix and id)
       
   911     //
       
   912     // @li IPv6 loopback is coded
       
   913     //    route = ELoopback, ::1/128, address= ::/128
       
   914     //    => Address match depends only on ELoopback prefix
       
   915     */
       
   916     TIp6Addr iId;       //< The Id value (aligned to the end)
       
   917     TUint8 iPrefix;     //< Number of bits to skip before id.
       
   918     //
       
   919     // Duplicate Address Detection
       
   920     //
       
   921     TUint8 iNS;         //< Number of NS sent for DAD
       
   922     /**
       
   923     // Generated address counter. If value is non-zero,
       
   924     // then this address has been randomly generated and
       
   925     // on duplicate address collision, it is legal to
       
   926     // regenerate another address. iGenerated counts
       
   927     // the number of address generations.
       
   928     */
       
   929     TUint8 iGenerated;  //< Number of address generations
       
   930     //
       
   931     // Address type
       
   932     //
       
   933     enum TAddressType
       
   934         {
       
   935         EProxy      = 2,    //< Do DAD, is not for me (forward)
       
   936         EAnycast    = 1,    //< Don't do DAD, is for me address
       
   937         ENormal     = 0,    //< Do DAD, is for me
       
   938         };
       
   939 private:
       
   940     TUint iType:2;
       
   941     TBool iPrimary;
       
   942     //
       
   943     // Address state
       
   944     //
       
   945     enum TState
       
   946         {
       
   947         ENoAddress  = 0,    //< 0 0 - unassigned initial state (no address present)
       
   948         EDuplicate  = 1,    //< 0 1 - address is duplicate
       
   949         EAssigned   = 2,    //< 1 0 - address fully available
       
   950         ETentative  = 3     //< 1 1 - address is tentative (DAD in progress)
       
   951         };
       
   952     TUint iState:2;
       
   953 public:
       
   954     /**
       
   955     // A flag to mark an internally generated IPv4 link-local address.
       
   956     //
       
   957     // There can only be at most one of these per interface.
       
   958     */
       
   959     TUint iIpv4LinkLocal:1;
       
   960     //
       
   961     //
       
   962     inline TInt AddressType() const { return (TInt)iType; }
       
   963     inline TInt AddressState() const { return (TInt)iState; }
       
   964     inline TBool IsSet() const { return iState != ENoAddress; };
       
   965     inline TBool IsTentative() const { return iState == ETentative; }
       
   966     inline TBool IsAssigned() const { return iState == EAssigned; }
       
   967     inline TBool IsDuplicate() const { return iState == EDuplicate; }
       
   968     inline TBool IsAnycast() const { return iType == EAnycast; }
       
   969     inline TBool IsProxy() const { return iType == EProxy; }
       
   970     inline TBool IsNormal() const { return iType == ENormal; }
       
   971     inline TBool IsPrimary() const { return iPrimary; }
       
   972     inline void SetInitial(const TInt aTentative) { iState = aTentative ? ETentative : EAssigned; }
       
   973     inline void SetDuplicate() { iState = EDuplicate; }
       
   974     inline void SetNoAddress() { iState = ENoAddress; }
       
   975     inline void SetType(const TInt aType)
       
   976         {
       
   977         iType = (TUint)aType;
       
   978         // ..anycast address is always assigned (NO DAD performed)
       
   979         if (aType == EAnycast) iState = EAssigned;
       
   980         }
       
   981     inline void SetPrimary(const TBool aPrimary ) { iPrimary = aPrimary; }
       
   982 #ifdef _LOG
       
   983     const TDesC &LogAddressType() const;
       
   984     const TDesC &LogAddressState() const;
       
   985 #endif
       
   986     //
       
   987     // Address Lifetimes (mainly for temporary address management)
       
   988     // (privacy extension for IPv6, RFC 3041)
       
   989     //
       
   990     TTime iCreated;     //< Creation Time (real time)
       
   991     TLifetime iVLT;     //< Valid lifetime (relative to iCRT)
       
   992     TLifetime iPLT;     //< Preferred lifetime (relative to iCRT)
       
   993     };
       
   994 
       
   995 #ifdef _LOG
       
   996 const TDesC &TIp6AddressInfo::LogAddressType() const
       
   997     {
       
   998     _LIT(KProxy,            "proxy ");
       
   999     _LIT(KAnycast,          "anycast ");
       
  1000     _LIT(KNormal,           "");
       
  1001     _LIT(KNormalPrimary,    "primary ");
       
  1002     _LIT(KInvalid,          "invalid ");
       
  1003     switch (iType)
       
  1004         {
       
  1005         case EProxy: return KProxy;
       
  1006         case EAnycast: return KAnycast;
       
  1007         case ENormal:
       
  1008             {
       
  1009             if( IsPrimary() )
       
  1010                 {
       
  1011                 return KNormalPrimary;
       
  1012                 }
       
  1013             else
       
  1014                 {
       
  1015                 return KNormal;
       
  1016                 }
       
  1017             }
       
  1018         default: break;
       
  1019         }
       
  1020     return KInvalid;
       
  1021     }
       
  1022 
       
  1023 const TDesC &TIp6AddressInfo::LogAddressState() const
       
  1024     {
       
  1025     _LIT(KNoAddress,    "none");
       
  1026     _LIT(KDuplicate,    "duplicate");
       
  1027     _LIT(KAssigned,     "assigned");
       
  1028     _LIT(KTentative,    "tentative");
       
  1029     switch (iState)
       
  1030         {
       
  1031         case EDuplicate: return KDuplicate;
       
  1032         case EAssigned: return KAssigned;
       
  1033         case ETentative: return KTentative;
       
  1034         default: break;
       
  1035         }
       
  1036     return KNoAddress;
       
  1037     }
       
  1038 
       
  1039 #endif
       
  1040 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
  1041 //RFC 5006 Changes
       
  1042 //
       
  1043 // CManageRdnssServerList::NewL()
       
  1044 // ****************************
       
  1045 // First Phase construction
       
  1046 CManageRdnssServerList* CManageRdnssServerList::NewL()
       
  1047     {
       
  1048     // Construct instance of type CMangeRdnssServerList
       
  1049     CManageRdnssServerList* me = new (ELeave)CManageRdnssServerList();
       
  1050     CleanupStack::PushL(me);
       
  1051     me->ConstructL();
       
  1052     CleanupStack::Pop();
       
  1053     return me;
       
  1054     }
       
  1055 
       
  1056 
       
  1057 // CManageRdnssServerList::ConstructL
       
  1058 // ****************************
       
  1059 // 
       
  1060 void CManageRdnssServerList::ConstructL()
       
  1061     {
       
  1062     
       
  1063     }
       
  1064 
       
  1065 
       
  1066 // CManageRdnssServerList::CManageRdnssServerList
       
  1067 // ****************************
       
  1068 // Sets Creation time for RDNSS entry
       
  1069 CManageRdnssServerList::CManageRdnssServerList():iRdnssArrayList(KRDNSSGranularity,_FOFF(TRdnssOptionData,iRDNSSaddress)),iRdnssLifetimeArrayList(KRDNSSGranularity) // set the granularity size to 4
       
  1070     {
       
  1071     //Construct iRdnssArrayList of size kRDNSSGranularity=4
       
  1072     //Set the initial current time stamp
       
  1073     
       
  1074     iCurrentTimeStamp.UniversalTime();
       
  1075     }
       
  1076 
       
  1077 
       
  1078 // CManageRdnssServerList::~CManageRdnssServerList
       
  1079 // ****************************
       
  1080 // Destructor to clean up iRdnssArrayList
       
  1081 CManageRdnssServerList::~CManageRdnssServerList()
       
  1082     {
       
  1083     iRdnssArrayList.Close();
       
  1084     iRdnssLifetimeArrayList.Close();
       
  1085     }
       
  1086 
       
  1087 
       
  1088 // CManageRdnssServerList::InsertRdnssEntryL
       
  1089 // ****************************
       
  1090 // Inserts RDNSS entry into RDNSS server list
       
  1091 // Array shall hold 4 DNS entries, 
       
  1092 // Returns ETrue if successful, if more than 4 received returns EFalse.
       
  1093 TBool CManageRdnssServerList::InsertRdnssEntryL(TRdnssOptionData& aRdnssEntry, TInt aIndex)
       
  1094     {
       
  1095     TInt numRdnssEntry = CountRdnssEntry();
       
  1096     if( numRdnssEntry < KRDNSSGranularity )// Shall hold only 4 entries
       
  1097         {
       
  1098         iRdnssArrayList.InsertL(aRdnssEntry, aIndex);
       
  1099         return ETrue;
       
  1100         }
       
  1101     return EFalse;
       
  1102     }
       
  1103 
       
  1104 
       
  1105 // CManageRdnssServerList::GetRdnssEntryRef
       
  1106 // ****************************
       
  1107 // Gets a reference to RDNSS entry
       
  1108 TRdnssOptionData& CManageRdnssServerList::GetRdnssEntryRef(TInt aIndex)
       
  1109     {
       
  1110     return iRdnssArrayList[aIndex];     
       
  1111     }
       
  1112 
       
  1113 
       
  1114 // CManageRdnssServerList::DeleteRdnssEntry
       
  1115 // ****************************
       
  1116 // Deletes RDNSS Entry for corresponding index
       
  1117 void CManageRdnssServerList::DeleteRdnssEntry(TInt aRdnssArrayIndex)
       
  1118     {   
       
  1119     // Removes entry from the array iRdnssServerList
       
  1120     iRdnssArrayList.Remove(aRdnssArrayIndex);
       
  1121     }
       
  1122 
       
  1123 
       
  1124 // CManageRdnssServerList::SetStoredLifeTime
       
  1125 // ****************************
       
  1126 // Sets StoredLifetime for a RDNSS Entry
       
  1127 void CManageRdnssServerList::SetStoredLifeTime(TInt aIndex, TRdnssOptionData aRdnssData)
       
  1128     {   
       
  1129     // Sets field Lifetime at the aIndex
       
  1130     iRdnssArrayList[aIndex].iStoredRdnssLifeTime = aRdnssData.iStoredRdnssLifeTime; 
       
  1131     }
       
  1132 
       
  1133 
       
  1134 // CManageRdnssServerList::Elapsed
       
  1135 // ****************************
       
  1136 // Returns the elapsed time with respect to created timestamp of RDNSS Entry
       
  1137 TLifetime CManageRdnssServerList:: Elapsed(const TTime &aStamp)const
       
  1138     {
       
  1139     TTimeIntervalSeconds elapsed;
       
  1140     aStamp.SecondsFrom(iCurrentTimeStamp, elapsed);
       
  1141     // Return 0, if time is earlier than time stamp (clock turned back?)
       
  1142     return (TLifetime) (elapsed.Int() < 0 ? 0 : elapsed.Int());
       
  1143     }
       
  1144 
       
  1145 
       
  1146 // CManageRdnssServerList::PrintRdnssServerList
       
  1147 // ****************************
       
  1148 // Prints RDNSS Entries
       
  1149 void CManageRdnssServerList::PrintRdnssServerList(TUint8 aIndex)
       
  1150     {
       
  1151     TRdnssOptionData rdnssEntry = GetRdnssEntryRef(aIndex);
       
  1152     TBuf<70> tmpsrc;
       
  1153     TInetAddr inetAddr(rdnssEntry.iRDNSSaddress);
       
  1154     TInetAddr::Cast(inetAddr).OutputWithScope(tmpsrc);      
       
  1155     LOG(Log::Printf(_L("\t [Index:%d],[RDNSS =%S],[Lifetime=%d]"),aIndex, &tmpsrc,rdnssEntry.iStoredRdnssLifeTime));
       
  1156     }
       
  1157 
       
  1158 
       
  1159 // CManageRdnssServerList::GetRdnssFlag
       
  1160 // ****************************
       
  1161 // Returns the RDNSS repository Flag
       
  1162 TInt& CManageRdnssServerList::GetRdnssFlag()
       
  1163     {
       
  1164     // iRdnsFlag shall be updated corresponding to each NameServer Entry.
       
  1165     // iRdnsFlag shall be 0x01 for first NameServer entry.
       
  1166     // iRdnsFlag shall be 0x03 for first and second NameServer entry.
       
  1167     // iRdnsFlag shall be 0x04 when Namserver entries are reset to KAFUnspec.
       
  1168     
       
  1169     return iRdnssFlag;
       
  1170     }
       
  1171 
       
  1172 
       
  1173 // CManageRdnssServerList::GetRemainingLifeTime
       
  1174 // ****************************
       
  1175 // Returns remaining life time for existing 'rdnssEntry' entry
       
  1176 TLifetime CManageRdnssServerList::GetRemainingLifeTime(TInt aRdnssEntryindex)
       
  1177     {
       
  1178     TRdnssOptionData rdnssEntry = GetRdnssEntryRef(aRdnssEntryindex);
       
  1179     TRdnssLifetime elapsedLifetime = ElapsedLifeTime(rdnssEntry);
       
  1180 #ifdef _DEBUG
       
  1181     TBuf<70> tmpsrc;
       
  1182     TInetAddr inetAddr(rdnssEntry.iRDNSSaddress);
       
  1183     TInetAddr::Cast(inetAddr).OutputWithScope(tmpsrc);
       
  1184     LOG(Log::Printf(_L("\t [[RDNSS =%S]][Elapsed Lifetime=%d,]"),&tmpsrc,elapsedLifetime));
       
  1185 #endif  
       
  1186     return elapsedLifetime;   
       
  1187     }
       
  1188 
       
  1189 
       
  1190 // CManageRdnssServerList::ElapsedLifeTime
       
  1191 // ****************************
       
  1192 // Compute the remaining life time for existing 'i' entry
       
  1193 TLifetime CManageRdnssServerList::ElapsedLifeTime(TRdnssOptionData aRdnssEntry)
       
  1194     {
       
  1195     // If iStoredRdnssLifetime is greater than current time, ie. entry is not expired, returns difference of
       
  1196     // (iStoredRdnssLifetime - curret_time).
       
  1197     // If current_time is greater than iStoredRdnssLifetime, then entry is expired, returns 0.
       
  1198     
       
  1199     TTime stamp;
       
  1200     stamp.UniversalTime();
       
  1201     const TLifetime current_time = Elapsed(stamp);
       
  1202                 
       
  1203     TLifetime elapsedLifetime = (aRdnssEntry.iStoredRdnssLifeTime > current_time)?
       
  1204                                                 (aRdnssEntry.iStoredRdnssLifeTime - current_time):0;
       
  1205     return elapsedLifetime;
       
  1206     }
       
  1207 
       
  1208 
       
  1209 // CManageRdnssServerList::RdnssEntryExists
       
  1210 // ****************************
       
  1211 // Verify RDNSS Entry Exists in RDNSS Server List
       
  1212 TBool CManageRdnssServerList::RdnssEntryExists(const TIp6Addr& aAddress, TInt& aArrIndex )
       
  1213     {
       
  1214     // Returns ETrue, with (aArrIndex)index of the (aAddress)RDNSS adress matched in iRdnssArrayList.
       
  1215     // Returns EFalse, if there exists no match of (aAddress)RDNSS address in iRdnssArrayList.
       
  1216     
       
  1217     TRdnssOptionData rdnssEntry;
       
  1218     TInt numRdnssEntry = CountRdnssEntry();
       
  1219     for(TInt rdnssIndex=0;rdnssIndex<numRdnssEntry;rdnssIndex++)
       
  1220         {   
       
  1221         rdnssEntry = GetRdnssEntryRef(rdnssIndex);
       
  1222         TInetAddr inetAddr(rdnssEntry.iRDNSSaddress);
       
  1223         if(aAddress.IsEqual(TInetAddr::Cast(inetAddr).Ip6Address()))
       
  1224             {
       
  1225             aArrIndex = rdnssIndex;
       
  1226             return ETrue;
       
  1227             }
       
  1228         else
       
  1229             {
       
  1230             continue;   
       
  1231             }
       
  1232         }
       
  1233     return EFalse;
       
  1234     }
       
  1235 
       
  1236 
       
  1237 // RdnssOrderFunc
       
  1238 // ****************************
       
  1239 // Function used to Order the List in Descending order
       
  1240 TInt RdnssOrderFunc( const TRdnssSortData &a, const TRdnssSortData &b)
       
  1241     {
       
  1242     if(a.iStoredRdnssLifeTime != b.iStoredRdnssLifeTime)
       
  1243         {
       
  1244         return a.iStoredRdnssLifeTime >b.iStoredRdnssLifeTime ? 1:-1;
       
  1245         }
       
  1246     else
       
  1247         return 0;
       
  1248     }
       
  1249 
       
  1250 
       
  1251 // CManageRdnssServerList::RdnssServerListSort
       
  1252 // ****************************
       
  1253 // Sorts on a temporary copied RDNSS Server List i.e iRdnssLifetimeArrayList on iStoredRdnssLifeTime Entry
       
  1254 void CManageRdnssServerList::RdnssServerListSort()
       
  1255     {
       
  1256     TLinearOrder<TRdnssSortData> order(RdnssOrderFunc);
       
  1257     iRdnssLifetimeArrayList.Sort(order);
       
  1258     }
       
  1259 
       
  1260 
       
  1261 // CManageRdnssServerList::RdnssServerListCopyL
       
  1262 // ****************************
       
  1263 // Copies contents from iRdnssArrayList to iRdnssLifetimeArrayList
       
  1264 void CManageRdnssServerList::RdnssServerListCopyL()
       
  1265     {
       
  1266     // Since sort on iRdnssArrayList alters the position related to NameServer entries,
       
  1267     // hence we copy the lifetime values of iRdnssArrayList to iRdnssLifetimeArrayList
       
  1268     // and then perform sort to determine the least lifetime entry.
       
  1269     
       
  1270     TInt rdnssCount = CountRdnssEntry(); // Get Number of Elements in iRdnssArrayList
       
  1271     TRdnssOptionData rdnssEntry;
       
  1272     TRdnssSortData lifetimeArrayList;
       
  1273     
       
  1274     for(TInt rdnssIndex=0;rdnssIndex<rdnssCount;rdnssIndex++)
       
  1275         {
       
  1276         rdnssEntry = GetRdnssEntryRef(rdnssIndex);
       
  1277         // Insert index position of iRdnssArrayList[] into iRdnssLifetimeArrayList[]      
       
  1278         lifetimeArrayList.iRdnssServerListIndex = rdnssIndex;
       
  1279         lifetimeArrayList.iStoredRdnssLifeTime  = rdnssEntry.iStoredRdnssLifeTime;
       
  1280         // Insert copied entries into iRdnssLifetimeArrayList
       
  1281         iRdnssLifetimeArrayList.InsertL(lifetimeArrayList,rdnssIndex);
       
  1282         }
       
  1283     }
       
  1284 
       
  1285 
       
  1286 // CManageRdnssServerList::GetRdnssLifetimeEntryRef
       
  1287 // ****************************
       
  1288 // Gets a reference to Lifetime entry in  RDNSS Lifetime list
       
  1289 TRdnssSortData& CManageRdnssServerList::GetRdnssLifetimeEntryRef(TInt aIndex)
       
  1290     {
       
  1291     return iRdnssLifetimeArrayList[aIndex];      
       
  1292     }
       
  1293 
       
  1294 
       
  1295 // CManageRdnssServerList::DeleteRdnssLifetimeEntry
       
  1296 // ****************************
       
  1297 // Delete Lifetime Entry for corresponding index in RDNSS Lifetime list
       
  1298 void CManageRdnssServerList::DeleteRdnssLifetimeEntry(TInt aRdnssArrayIndex)
       
  1299     {
       
  1300     // Removes entry from the array iRdnssLifetimeArrayList
       
  1301     iRdnssLifetimeArrayList.Remove(aRdnssArrayIndex); 
       
  1302     }
       
  1303 
       
  1304 
       
  1305 // CManageRdnssServerList::RdnssLifetimeListDelete
       
  1306 // ****************************
       
  1307 // Delete All Lifetime Entries in Rdnss Lifetime List 
       
  1308 void CManageRdnssServerList::RdnssLifetimeListDelete()
       
  1309     {
       
  1310     TInt rdnssCount;
       
  1311     rdnssCount=CountRdnssLifetimeEntry();
       
  1312     for(;rdnssCount!=0;rdnssCount--)
       
  1313         {
       
  1314         DeleteRdnssLifetimeEntry(0); // 0 - Remove all Entries in RdnssDummyArrayList        
       
  1315         
       
  1316 #ifdef _DEBUG
       
  1317         LOG(Log::Printf(_L("\t ...RdnssLifetimeListDelete.[Deleted Entry: %d]"),rdnssCount));
       
  1318 #endif      
       
  1319         }   
       
  1320     }
       
  1321 
       
  1322 
       
  1323 // CManageRdnssServerList::PrintRdnssLifetimeList
       
  1324 // ****************************
       
  1325 // Prints Lifetime Entries associated with iRdnssServerList Table 
       
  1326 void CManageRdnssServerList::PrintRdnssLifetimeList(TUint8 aIndex)
       
  1327     {
       
  1328     TRdnssSortData rdnssEntry = GetRdnssLifetimeEntryRef(aIndex);
       
  1329 #ifdef _DEBUG       
       
  1330     LOG(Log::Printf(_L("\t [Index:%d],[RDNSSIndex =%d],[Lifetime=%d]"),aIndex, rdnssEntry.iRdnssServerListIndex,rdnssEntry.iStoredRdnssLifeTime));
       
  1331 #endif    
       
  1332     }
       
  1333 
       
  1334 
       
  1335 // CManageRdnssServerList::RdnssExpireLeastEntry
       
  1336 // ****************************
       
  1337 // Expire an RDNSS Entry with Least Lifetime in RDNSS Server List
       
  1338 void CManageRdnssServerList::RdnssExpireLeastEntry(TRdnssOptionData aRdnssRcvData)
       
  1339     {
       
  1340     // Copy the contents from iRdnssArrayList to iRdnssLifetimeArrayList and perform sort on later
       
  1341     // to find Worse Lifetime Entry corresponding to StoredLifetime. 
       
  1342     
       
  1343     RdnssServerListCopyL();    
       
  1344     
       
  1345     //Sort iRdnssLifetimeArrayList using RArray Sort.
       
  1346     RdnssServerListSort();    
       
  1347     
       
  1348     //Get the Least Lifetime entry available at Index 0
       
  1349     TRdnssSortData rdnssData = GetRdnssLifetimeEntryRef(0);    
       
  1350     TInt rdnssServerListIndex = rdnssData.iRdnssServerListIndex;      
       
  1351     DeleteRdnssEntry(rdnssServerListIndex);    
       
  1352     LOG(Log::Printf(_L("\t Deleted an Entry and Insert Successful")));
       
  1353     InsertRdnssEntryL(aRdnssRcvData, 0);
       
  1354 #ifdef _DEBUG    
       
  1355     for(TUint8 index=0;index<CountRdnssLifetimeEntry();index++)
       
  1356         {   
       
  1357         PrintRdnssLifetimeList(index);      
       
  1358         }    
       
  1359 #endif
       
  1360     // Flush all the entries in iRdnssLifetimeArrayList, since its no more required
       
  1361     RdnssLifetimeListDelete();
       
  1362     }
       
  1363 
       
  1364 
       
  1365 // CManageRdnssServerList::RdnssServerListDelete
       
  1366 // ****************************
       
  1367 // Expire All RDNSS Entries in RDNSS Server List since router lifetime is 0
       
  1368 void CManageRdnssServerList::RdnssServerListDelete()
       
  1369     {
       
  1370     TInt rdnssCount;
       
  1371     rdnssCount=CountRdnssEntry();
       
  1372     for(;rdnssCount!=0;rdnssCount--)
       
  1373         {
       
  1374         DeleteRdnssEntry(0); // 0 , since its last entry in iRdnssServerList        
       
  1375 #ifdef _DEBUG
       
  1376         LOG(Log::Printf(_L("\t ...RdnssServerListDelete.[Deleted Entry: %d]"),rdnssCount));
       
  1377 #endif      
       
  1378         }   
       
  1379     }
       
  1380 
       
  1381 
       
  1382 // CManageRdnssServerList::RdnssServerListSync
       
  1383 // ****************************
       
  1384 // Syncrhonises RDNSS server list 
       
  1385 TBool CManageRdnssServerList::RdnssServerListSync(TInetAddr& aNameSer1, TInetAddr& aNameSer2)
       
  1386     {
       
  1387     // Verfifies elapsed Lifetime is equal to 0 for each RDNSS Entry in iRdnssArrayList.
       
  1388     // If elapsed Lifetime is zero, then delete corresponding entry in iRdnssArrayList.
       
  1389     // If entry corresponds to RDNSS NameServer Repository[0 or 1], 
       
  1390     // Synchronise NameServer Repository Entries in iRdnssArrayList and update iNameSer1 and iNameSer2 entries in CIp6Interface
       
  1391     
       
  1392     TRdnssLifetime elapsedLifetime;
       
  1393     TRdnssOptionData rdnssEntry;
       
  1394     TBool sendRdnssRS = EFalse;    
       
  1395         
       
  1396     for(TInt rdnssIndex=0;rdnssIndex<CountRdnssEntry();++rdnssIndex)
       
  1397         {   
       
  1398             rdnssEntry = GetRdnssEntryRef(rdnssIndex);
       
  1399             elapsedLifetime = ElapsedLifeTime(rdnssEntry);
       
  1400 #ifdef _DEBUG
       
  1401             TBuf<70> tmpsrc;
       
  1402             TInetAddr inetAddr(rdnssEntry.iRDNSSaddress);
       
  1403             TInetAddr::Cast(inetAddr).OutputWithScope(tmpsrc);
       
  1404             LOG(Log::Printf(_L("\t [[RDNSS =%S]][Elapsed Lifetime=%d,]"),&tmpsrc,elapsedLifetime));
       
  1405 #endif      
       
  1406             // RDNSS entry is expired since its not updated by RA. 
       
  1407             if(elapsedLifetime==0)
       
  1408                 {
       
  1409                 // Verify whether expired entry is a preferred entry matching index 0 or index 1 corresponding to iNameSer1/iNameSer2,
       
  1410                 // If so reset the dns_flag. 
       
  1411                  if((rdnssIndex == 0) || (rdnssIndex == 1)) 
       
  1412                      {                                       
       
  1413                      RdnssNameServerSync(rdnssIndex,aNameSer1,aNameSer2);                               
       
  1414                      }
       
  1415                  else
       
  1416                      {
       
  1417                     //Expired Entry is not a Preferred Entry, remove the corresponding entry from iRdnssArrayList[i].    
       
  1418                      DeleteRdnssEntry(rdnssIndex);                                       
       
  1419                      LOG(Log::Printf(_L("\t ...RDNSS Entry Deleted[Index=%d,]"),rdnssIndex));                                        
       
  1420                      }              
       
  1421                 }
       
  1422             // RDNSS entry is about to expire, need to refresh RDNSS entry by initiating a RS
       
  1423             // Since CIP6Interface::Timeout handler expires for every 30 seconds.
       
  1424             if(elapsedLifetime<=RDNSS_REFRESH_TIMEOUT)
       
  1425                 {                
       
  1426                 return sendRdnssRS = ETrue;
       
  1427                 }
       
  1428         } //End of for()  
       
  1429     return sendRdnssRS;
       
  1430     }
       
  1431 
       
  1432 
       
  1433 // CManageRdnssServerList::RdnssNameServerUpdate
       
  1434 // ****************************
       
  1435 // Update NameServer Repository iNameSer1/iNameSer2 in CIp6Interface from RDNSS server list
       
  1436 void CManageRdnssServerList::RdnssNameServerUpdate(TInetAddr& aNameSer, TUint8 aNameServerIndex)
       
  1437     {    
       
  1438     // If RdnssArrayList exist, just update aNameSer(iNameSer1/iNameSer2 entries in CIp6Interface) with appropriate dns address.
       
  1439     // If RDNSSArrayList doesn't exist, Need to reset aNameSer(iNameSer1/iNameSer2 in CIp6Interface) to KAFUnspec.
       
  1440     
       
  1441     if( CountRdnssEntry()>aNameServerIndex )     
       
  1442         {   
       
  1443         TRdnssOptionData rdnssEntry = GetRdnssEntryRef(aNameServerIndex);
       
  1444         
       
  1445         // aNameSerIndex for iNameSer1 ==> 1.
       
  1446         // aNameServerIndex for iNameSer2 ==> 2.
       
  1447         
       
  1448         // If NameServer entry doesnt exist, configure iNameSer1/iNameSer2 and mark "dns_changed" respect to repository being set..
       
  1449         if( (iRdnssFlag&(aNameServerIndex+1))==0) 
       
  1450             {
       
  1451             aNameSer.SetAddress(rdnssEntry.iRDNSSaddress.Ip6Address());
       
  1452             iRdnssFlag |= (aNameServerIndex + 1);          
       
  1453             }
       
  1454         // If Nameserver entry exists, needs to be refreshed due to fresh update of iRdnssArrayList.
       
  1455         else 
       
  1456             {
       
  1457             aNameSer.SetAddress(rdnssEntry.iRDNSSaddress.Ip6Address());
       
  1458             }
       
  1459         LOG(Log::Printf(_L("\t Updating NameServer Repository: NameSerIndex=%d, RdnssFlag=%d Lifetime=%d"),aNameServerIndex,iRdnssFlag,rdnssEntry.iStoredRdnssLifeTime));
       
  1460         }
       
  1461     else
       
  1462         {
       
  1463         // Dont reset iRdnsFlag, since there is a single dns address yet to be expired.
       
  1464         // RdnssNameServerSync() shall delete repository entry, provided elapsed time is 0 and also shall reset iRdnssFlag appropriately.
       
  1465         LOG(Log::Printf(_L("\t Reset NameServer Repository: NameSerIndex=%d"),aNameServerIndex));
       
  1466         aNameSer.Init(KAFUnspec);        
       
  1467         }
       
  1468     }
       
  1469 
       
  1470 
       
  1471 // CManageRdnssServerList::RdnssNameServerReset
       
  1472 // ****************************
       
  1473 // Reset Rdnss Namserver Repository Upon expiry of lifetime to KAFUnspec.
       
  1474 void CManageRdnssServerList::RdnssNameServerReset(TInetAddr& aNameSer, TInt& aDdnsflag )
       
  1475     {
       
  1476     aNameSer.Init(KAFUnspec);
       
  1477     // mark "dns changed" respect to repository being deleted.
       
  1478     aDdnsflag = aDdnsflag & 4;
       
  1479     }
       
  1480 
       
  1481 
       
  1482 // CManageRdnssServerList::RdnssNameServerSync
       
  1483 // ****************************
       
  1484 // Syncrhonise NameServer Repository entries in RDNSS server list.
       
  1485 void CManageRdnssServerList::RdnssNameServerSync(TInt aRdnssIndex, TInetAddr& aNameSer1, TInetAddr& aNameSer2)
       
  1486     {
       
  1487     // Since NameServer Entry is expired, remove the corresponding entry from iRdnssArrayList.
       
  1488     // Reset iNameSer1/iNameSer2 to KAFUnsepc
       
  1489     
       
  1490     TInetAddr& nameSer = aRdnssIndex==0?aNameSer1:aNameSer2;
       
  1491     RdnssNameServerReset(nameSer,GetRdnssFlag());
       
  1492     DeleteRdnssEntry(aRdnssIndex);
       
  1493     LOG(Log::Printf(_L("\t ...RDNSS Repository Entry Deleted[Index=%d,]"),aRdnssIndex));
       
  1494     }
       
  1495 
       
  1496 
       
  1497 // CManageRdnssServerList::RdnssServerListUpdate
       
  1498 // ****************************
       
  1499 // Append RDNSS Entry in RDNSS Server List or update existing entry.
       
  1500 void CManageRdnssServerList::RdnssServerListUpdate(TInet6OptionICMP_DnsInformationV1 aRdnssIcmpOption, TUint8 aNumRdnssAddr)
       
  1501     {
       
  1502     // Find Whether Received Entry Exists
       
  1503     // If found existing Entry, update stored lifetime.
       
  1504     // Else create a new Entry.
       
  1505     // If no room to accomodate a new Entry, find Worse Entry and delete.
       
  1506     // Upon successful deletion,Store new Entry.    
       
  1507     
       
  1508     TRdnssOptionData rdnssRcvData;
       
  1509     TInt rdnssOptionPktSize;
       
  1510         
       
  1511     for(TUint8 rdnssAddrCount=0; rdnssAddrCount< aNumRdnssAddr;++rdnssAddrCount) 
       
  1512         {
       
  1513         //Fetch the first RDNSS address from RDNSS option
       
  1514         rdnssOptionPktSize = aRdnssIcmpOption.HeaderLength()+((rdnssAddrCount+1)*RDNSSADDRSIZE);
       
  1515         
       
  1516         const TIp6Addr &addr  = aRdnssIcmpOption.GetNextAddress(rdnssOptionPktSize-RDNSSADDRSIZE);
       
  1517         const TRdnssLifetime lifetime = aRdnssIcmpOption.Lifetime();
       
  1518         rdnssRcvData.iRDNSSaddress.SetAddress(addr);
       
  1519         
       
  1520         TInt rdnssArrayIndex;
       
  1521         
       
  1522         //Find this entry exist in RDNSS Server List
       
  1523         if(!RdnssEntryExists(addr, rdnssArrayIndex))
       
  1524             {
       
  1525             //Entry doesnt exist,Try to Insert it infront of the iRdnssArrayList            
       
  1526             //Before updating the lifetime, convert into seconds to determine it is expired.
       
  1527             TTime stamp;
       
  1528             stamp.UniversalTime();
       
  1529             const TRdnssLifetime current_time = Elapsed(stamp);     
       
  1530             rdnssRcvData.iStoredRdnssLifeTime = lifetime + current_time ; // (It should be current system time + lifetime ...in seconds )
       
  1531             LOG(Log::Printf(_L("\t Received Entry with Lifetime: %d"),rdnssRcvData.iStoredRdnssLifeTime));          
       
  1532                             
       
  1533             if(!InsertRdnssEntryL(rdnssRcvData, 0))
       
  1534                 {   
       
  1535                 LOG(Log::Printf(_L("\t Insert Unsuccessful,Received More than 4 ENTRIES")));
       
  1536                 //If insert is unsuccessful, then try to find room for new entry.               
       
  1537                 RdnssExpireLeastEntry(rdnssRcvData);
       
  1538                 }   
       
  1539             }
       
  1540             else // Found an entry, need to update existing entry with suitable lifetime 
       
  1541                 {
       
  1542                 // Delete an entry , if lifetime is zero.
       
  1543                 if( lifetime==0 )
       
  1544                     {
       
  1545                     // Entry is expired, remove the corresponding entry from iRdnssArrayList[i].
       
  1546                     DeleteRdnssEntry(rdnssArrayIndex);
       
  1547                     continue;
       
  1548                     }
       
  1549                 else
       
  1550                 //Update the entry 'i' with received lifetime, if remaininglifetime is greater than 0.
       
  1551                     {
       
  1552                     TTime stamp;
       
  1553                     stamp.UniversalTime();
       
  1554                     const TRdnssLifetime current_time = Elapsed(stamp);
       
  1555                     // (It should be current system time + lifetime ...in seconds )
       
  1556                     rdnssRcvData.iStoredRdnssLifeTime = lifetime + current_time;
       
  1557                     SetStoredLifeTime(rdnssArrayIndex,rdnssRcvData);
       
  1558                     }
       
  1559                 }
       
  1560         }//end of For
       
  1561     
       
  1562     }
       
  1563 
       
  1564 
       
  1565 // CManageRdnssServerList::RdnssProcessOptionData
       
  1566 // ****************************
       
  1567 // Process received RDNSS Option Data from Router Adevertisement.
       
  1568 void CManageRdnssServerList::RdnssProcessOptionData(TInet6OptionICMP_DnsInformationV1 aRdnssOption, TUint8 aNumRdnssAddr )
       
  1569     {
       
  1570     RdnssServerListUpdate(aRdnssOption,aNumRdnssAddr);
       
  1571 #ifdef _DEBUG
       
  1572     LOG(Log::Printf(_L("\tIF RDNSS TABLE PRINTED")));   
       
  1573     for(TUint8 index =0;index<CountRdnssEntry();index++)
       
  1574         {   
       
  1575         PrintRdnssServerList(index);
       
  1576         }
       
  1577 #endif  
       
  1578     }
       
  1579 
       
  1580 
       
  1581 // CManageRdnssServerList::RdnssParseOptionHdr
       
  1582 // ****************************
       
  1583 // Parse received RDNSS Option Header from RA.
       
  1584 // Returns True, if option length is > RDNSSMINLEN, else returns False.
       
  1585 TBool CManageRdnssServerList::RdnssParseOptionHdr(TInet6OptionICMP_DnsInformationV1 aRdnssOption, TUint8& aNumRdnssAddr )
       
  1586     {
       
  1587     const TUint8 length = aRdnssOption.Length();    
       
  1588     //Find the total length field since it is units of 8 octets and discard if less than RDNSSMINLEN.
       
  1589     TUint8 opt_len = (length)* RDNSSOPTION_HDRLENGTH;                       
       
  1590     if(opt_len < RDNSSMINLEN)
       
  1591         {
       
  1592         return EFalse;
       
  1593         }           
       
  1594     else
       
  1595         {
       
  1596         aNumRdnssAddr = (length-1)/2;
       
  1597         return ETrue;   
       
  1598         }   
       
  1599     }
       
  1600 
       
  1601 //RFC 5006 Changes  for RDNSS_OPTION
       
  1602 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
  1603 
       
  1604 
       
  1605 // ***********
       
  1606 // CIp6Address
       
  1607 // ***********
       
  1608 // Holds additional id's assigned to this interface, to be used for
       
  1609 // generated ids as described in privacy extension RFC-3041.
       
  1610 //
       
  1611 class CIp6Address : public CBase
       
  1612     {
       
  1613 public:
       
  1614     TIp6AddressInfo iInfo;
       
  1615     };
       
  1616 
       
  1617 // *************
       
  1618 // CIp6Interface
       
  1619 // *************
       
  1620 
       
  1621 class CIp6Interface : public CBase, public MInterface
       
  1622     {
       
  1623     friend class CIp6Flow;
       
  1624     friend class CIp6Manager;
       
  1625     friend class CIp6NifUser;
       
  1626     friend class CIp6Route;
       
  1627     // *********
       
  1628     // *WARNING*
       
  1629     // *********
       
  1630     // When adding members/fields into this class, do remember
       
  1631     // to check the "reset information" in Reset() method,
       
  1632     // if value needs to be cleared between interfaces reusing
       
  1633     // this same structure! -- msa
       
  1634     //
       
  1635 public:
       
  1636     CIp6Interface(CIp6Manager &aMgr, TUint aIndex, const TDesC &aName);
       
  1637     ~CIp6Interface();
       
  1638 
       
  1639     TUint32 Index() const;
       
  1640     const TDesC &Name() const;
       
  1641     TUint32 Scope(const TScopeType aType) const;
       
  1642 
       
  1643     void Reset(const TInt aKeepNif = 0);// set instance back to initial state.
       
  1644 
       
  1645     void Timeout(const TTime &aStamp);  // Timer expiration event handler
       
  1646 
       
  1647 
       
  1648     CIp6Route *SelectSource(TIp6Addr &aSrc, const TIp6Addr & aDst) const;
       
  1649     void SetPrefix(const TIp6Addr &aPrefix, const TUint aLength, const TInt aForce, const TLifetime aLifetime = KLifetimeForever, const TLifetime aPeferred = KLifetimeForever);
       
  1650 
       
  1651     //
       
  1652     // Return the number of seconds between the given time (aStamp) and
       
  1653     // the time when interface was activated (iTimeStamp). aStamp must
       
  1654     // always be same of after iTimeStamp.
       
  1655     TLifetime Elapsed(const TTime &aStamp) const;
       
  1656 
       
  1657     //
       
  1658     // Methods for the Id part of the Ip6 addresses
       
  1659     //
       
  1660     void UpdateIdRoutes(const TIp6AddressInfo &aId, const TLifetime aLifetime);
       
  1661     TInt SetId(TIp6AddressInfo &aId, const TIp6Addr &aAddr, const TInt aPrefix, const TInt aAddressType);
       
  1662     TInt AddId(const TSockAddr& aId);   // returns 0 = not changed, 1 = changed
       
  1663     TInt AddId(const TIp6Addr &aId, const TInt aPrefix, const TInt aAddressType = TIp6AddressInfo::ENormal, const TBool aForcePrimary = EFalse);    // returns 0 = not changed, 1 = changed
       
  1664     TIp6AddressInfo* GetId(const TIp6Addr &aAddr) const;
       
  1665     TInt RemId(const TIp6AddressInfo *const aId);
       
  1666     // SetMtu sets the send MTU. Currently called from RouterAdvert handler
       
  1667     // and it might be dubious thing to unconditionally change the interface
       
  1668     // send Mtu this way (could perhaps constrain it by the interface reported
       
  1669     // value). CHECK THIS LATER! -- msa
       
  1670     void SetMtu(TInt aMtu, TInt aMin);
       
  1671     // StartSending handles the StartSending from the interface
       
  1672     TInt StartSending();
       
  1673     inline TInt IsNetdial() const {return iName.Length() == 0; }
       
  1674     inline TInt NeedsND() const { return iFeatures & KIfNeedsND; }
       
  1675     // ...can send RS only if IPv6 enabled and supports multicast
       
  1676     inline TInt CanSendRS() const { return iIsIPv6 && (iFeatures & KIfCanMulticast); }
       
  1677     //
       
  1678     // IsMyAddress returns non-NULL, if aAddr matches any of the
       
  1679     // current src addresses for this interface. The returned ptr
       
  1680     // indicates the ID that matched.
       
  1681     //
       
  1682     // Normally proxy and anycast addresses are not "my addresses", but
       
  1683     // neigbour discovery needs to treat them as own, thus allow aAll != 0
       
  1684     // to include them into "my address"..
       
  1685     //
       
  1686     TIp6AddressInfo *IsMyAddress(const TIp6Addr &aAddr, const TInt aAll = 0) const;
       
  1687     // IsForMeAddress returns TRUE, if aAddr is for me (almost
       
  1688     // same as IsMyAddr, but additionally returns true for multicast
       
  1689     // and anycast addresses.
       
  1690     TBool IsForMeAddress(const TIp6Addr &aAddr) const;
       
  1691     //
       
  1692     // IsMyId returns non-NULL, if aAddr matches any of the
       
  1693     // id's for the interface (also tentative ones!)
       
  1694     TIp6AddressInfo *IsMyId(const TIp6Addr &aAddr) const;
       
  1695     //
       
  1696     // IsMyPrefix returns non-NULL, if aAddr matches any of
       
  1697     // the MYPREFIX entries in the route list.
       
  1698     CIp6Route *IsMyPrefix(const TIp6Addr &aAddr, const TIp6AddressInfo &aId) const;
       
  1699     //
       
  1700     // Update flow counts (iFlows). Change can positive
       
  1701     // or negative.
       
  1702     //
       
  1703     void UpdateFlowCount(TInt aChange);
       
  1704     // Send a packet to the interface
       
  1705     TInt Send(RMBufChain& aPacket, CProtocolBase* aSourceProtocol=NULL);
       
  1706     TInt UpdateMulticast(const TIp6Addr &aMulticast, TLifetime const aLifetime = KLifetimeForever);
       
  1707     void GetDefGateway(const TBool aIsIPv4, TInetAddr &aAddr) const;
       
  1708     CIp6Route *GetRoute(const TIp6Addr &aAddr, TInt aPrefix, TUint aFlags, const TSockAddr *const aGateway = NULL, const TLifetime *const aLifetime = NULL);
       
  1709     void RemoveRoute(CIp6Route *aRoute);
       
  1710     void MoveToFront(CIp6Route *aRoute);    // Move the route to the first in the list
       
  1711     void NotifyFlows(TInt aState, TBool aForce = EFalse) const; // External change in interface/driver
       
  1712     void NotifyFlowsPmtu(const TUint aPmtu) const;  // Notify attached flows about changed Path MTU 
       
  1713     TInt SetChanged(const TInt aScope = 0) const;// Set iChanged on attached flows
       
  1714     CIp6Route *SelectNextHop(const TIp6Addr &aDst, const TIp6Addr &aSrc, CIp6Route *aRoute);
       
  1715 
       
  1716     CIp6Route *FindNeighbor(const TIp6Addr &aDst) const;
       
  1717     CIp6Route *FindRoute(const TIp6Addr &aDst, CIp6Route *aRoute) const;
       
  1718 
       
  1719     //
       
  1720     // Accessing the main components uniformly independent of the class
       
  1721     // (when linkages between classes change, just change these to reflect
       
  1722     // the change, and the rest of the code should work unchanged)
       
  1723     //
       
  1724     inline CIp6Manager &Interfacer() const { return iInterfacer; };
       
  1725     //
       
  1726     // Set/reset a timer event on the current object
       
  1727     //
       
  1728     void SetTimer(TUint32 aDelay) { Interfacer().SetTimer(iTimeout, aDelay); }
       
  1729     // CancelTimer/IsTimerActive are just syntactic sugar, because
       
  1730     // of the SetTimer: if one uses SetTimer and hides iTimeout, then
       
  1731     // all uses of iTimeout should be "hidden" too!
       
  1732     inline void CancelTimer() { iTimeout.Cancel(); }
       
  1733     inline TBool IsTimerActive() { return iTimeout.IsActive(); }
       
  1734     TInt HaveIp4LinkLocal();
       
  1735     TBool HasIpv4LinkLocalAddr() const  { return FindIpv4LinkLocalAddr() ? ETrue : EFalse; }
       
  1736     TInt SetIpv4LinkLocal(TUint aFlag);
       
  1737     const TIp6AddressInfo* FindIpv4LinkLocalAddr() const;
       
  1738     
       
  1739     // Values given by HaveIp4LinkLocal(), equal to possible tcpip6.ini configuration settings.
       
  1740     enum EV4LLEnums
       
  1741         {
       
  1742         EV4LLDisabled = 0,              //< Do not use IPv4 link-local addresses in any case.
       
  1743         EV4LLAlways,                    //< Use IPv4 link-local address whenever possible.
       
  1744         EV4LLConditional,               //< Use IPv4 link-local address if Nif does not have configured address.
       
  1745         EV4LLConfigDaemonControlled,    //< Do not use IPv4 link-local address if we succeed in acquiring an IP from a server (e.g., DHCP).  If a server is not present or unavailable, automatically configure link-local address.
       
  1746         EV4LLUnknown                    //< Status of IPv4 link-local setting is unknown (ini file haven't been read yet).
       
  1747         };
       
  1748     CIp6Route *StartProbeND(const TIp6Addr &aSrc, const TIp6Addr &aDst);
       
  1749 
       
  1750 private:
       
  1751     // DoBind is called when NifIfBase instance becomes available
       
  1752     TInt DoBind(CIp6NifUser *aNifUser, CNifIfBase *aIf);
       
  1753     TInt RandomAddress(TIp6Addr &aAddr, TUint aPrefix, TUint aN);
       
  1754     void DuplicateAddress(TIp6AddressInfo *aId, TBool &aDefendIPAddress, const TBool aGratuitousArp = EFalse);
       
  1755     TInt ConfigureAddress(const TIp6Addr &aAddr, const TUint aMaskLength, const TBool aForcePrimary = EFalse);
       
  1756     TInt ConfigureLinkLocal(TUint32 aConfAddr);
       
  1757     TIp6AddressInfo* FindInternalIpv4LinkLocalAddr();
       
  1758     void UpdateNameServers(const TInetAddr &ns1, const TInetAddr &ns2, const TInt aOverride = 0);
       
  1759     TInt Update4(TInt aTransition); // Try IPv4 specific setup
       
  1760     TInt Update6(TInt aTransition); // Try IPv6 specific setup
       
  1761     TInt SendNeighbors(TInt aMessageType, CIp6Route *aDestination, const TIp6Addr &aTarget, const TIp6Addr *const aSrc = NULL);
       
  1762     TInt IcmpHandler(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo, TInet6Packet<TIcmpNdHeader>  &aNd);
       
  1763 #ifdef ARP
       
  1764     TInt ArpHandler(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo, TInet6Packet<TInet6HeaderArp> &aArp);
       
  1765 #endif
       
  1766     void Ip4RedirectHandler(const RMBufRecvPacket &aPacket, const RMBufRecvInfo &aInfo);
       
  1767 
       
  1768     void SetReachableTime();
       
  1769     void SetRetransTimer();
       
  1770     void RouterChanged(CIp6Route *const aRouter);
       
  1771     void SetAddressAndScope(TSockAddr &aAddr, const TSockAddr &aSrc) const;
       
  1772 
       
  1773     void NotifyAddressEvent(TUint aEventType, const TIp6Addr &aPrefix,
       
  1774         const TUint aLength,
       
  1775         const CIp6Route *aPrefixEntry, const TIp6AddressInfo &aAddress) const;
       
  1776 
       
  1777     // Send notification about changed route to event manager
       
  1778     void NotifyRouteEvent(TUint aEventType, const CIp6Route *aRoute, const TLifetime aLifetime = 0) const;
       
  1779 
       
  1780     void NotifyInterfaceEvent(TUint aEventType) const;
       
  1781     
       
  1782     void NotifyMulticastEvent(TUint aEventType, const TIp6Addr &aMulticast, const TLifetime aLifetime) const;
       
  1783 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
  1784     //Do DAD for the Global address
       
  1785     void PerformDADForGlobalAddress(const TIp6Addr &aPrefix,const TUint aLength);
       
  1786 #endif	//SYMBIAN_TCPIPDHCP_UPDATE
       
  1787 
       
  1788     CIp6Manager &iInterfacer;               //
       
  1789     const TName iName;                      //< The name of the interface.
       
  1790     TInt iState;                            //< Interface state: PENDING, READY, HOLD or DOWN.
       
  1791     TTime iTimeStamp;                       //< Base Time Reference for address lifetimes.
       
  1792     TUint iSequence;                        //< Incremented once for each address deleting event.
       
  1793     TIp6AddressInfo iAddress;               //< Assigned addresses.
       
  1794     CIp6Route *iRouteList;                  //< All routes.
       
  1795     TInt iSMtu;                             //< Send MTU (cached value, could also just ask it always from the interface)
       
  1796     TInt iRMtu;                             //< Receive MTU (cached value, could also just ask it always from the interface)
       
  1797     TInt iSpeedMetric;                      //< (cached value from the interface)
       
  1798     TUint iFeatures;                        //< (cached value from the interface)
       
  1799     TInetAddr iNameSer1;                    //< 1. Name server address (if defined)
       
  1800     TInetAddr iNameSer2;                    //< 2. Name server address (if defined)
       
  1801     TInt iPMtu;                             //< Path MTU for this interface
       
  1802     TUint iRouters;                         //< Current number of routers
       
  1803     TUint8 iRetryRS:8;                      //< ...only used in startup for RS sols.
       
  1804     TUint8 iHopLimit:8;                     //< Current Default Hoplimit on this link
       
  1805     TUint iIsIPv6:1;                        //< Interface configured for IPv6, if set
       
  1806     TUint iIsIPv4:1;                        //< Interface configured for IPv4, if set
       
  1807     TUint iIsSuspended:1;                   //< TRUE if interface is suspended.
       
  1808     // Use of link-local IPv4 addresses. 0: link-locals disabled, 1: use if no IPv4 address is read from Nif,
       
  1809     // 2: always attach link-local address to interface, 3: use link-local address if no IPv4 address is read from Nif or configuration daemon
       
  1810     TUint iIpv4Linklocal:3;
       
  1811 
       
  1812     /** Set IS ROUTER flag to neighbour advertisement message.
       
  1813     // Note! This is a low level functionality flag, and does not have any
       
  1814     // other semantics, like enabling general router functionality.
       
  1815     */
       
  1816     TUint iIsRouter:1;
       
  1817 
       
  1818     TInetNdConfig iND;      //< Current Neighbor Discovery parameters (base values)
       
  1819     TUint iReachableTime;   //< User::TickCount units, computed from base values
       
  1820     TUint iRetransTimer;    //< Timer units, computed from base values
       
  1821     /**
       
  1822     // Hardware address of the interface.
       
  1823     // @li
       
  1824     //   if iHwAddr.Family() is KAFUnspec (= 0), then link layer does not support
       
  1825     //   link layer addresses
       
  1826     // @li
       
  1827     //   if iHwAddr.Family() is not KAFUnspec, then this contains the current
       
  1828     //   link layer address of this interface (if known). Also, the Family
       
  1829     //   is the assumed address family of the link layer addresses of the
       
  1830     //   other nodes on this link.
       
  1831     */
       
  1832     TLinkAddr iHwAddr;
       
  1833     CNifIfBase *iNifIf;     //< Interface instance
       
  1834     /**
       
  1835     // Held packets when interface has blocked (iState == EFlow_HOLD).
       
  1836     // This queue should normally be ALWAYS empty. It only gets used
       
  1837     // when some component of the system does not honour the "flow
       
  1838     // blocking" singal (return 0 from Send).
       
  1839     //
       
  1840     // Currently, IP fragmenter is such component due to posthooks.
       
  1841     // It would have hard time handling the situation (because it
       
  1842     // cannot be sure which interface the packets actually end up!)
       
  1843     */
       
  1844     RMBufPktQ iHoldQueue;
       
  1845     //
       
  1846     // CIp6Manager Work Space
       
  1847     //
       
  1848     TInt iFlows;            //< Number of flows leading to this interface from routes
       
  1849     CIp6Interface *iNext;   //< Interface List Link (head in CIp6Manager)
       
  1850     //
       
  1851     // iNifUser always points to one of the MNifIfUser instances within
       
  1852     // CIp6Manager. It is initialized in when interface is created and
       
  1853     // only updated in DoBind().
       
  1854     // [the need for this needs to be re-examined -- msa]
       
  1855     //
       
  1856     CIp6NifUser *iNifUser;
       
  1857     // The Scope Identifiers assigned to this interface
       
  1858     TInetScopeIds iScope;
       
  1859 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
  1860     CManageRdnssServerList *iRdnssList; //RFC-5006      
       
  1861     // Global flag, used while composing global address from prefix of RA (with 'A' flag set)
       
  1862     TBool iGlobalflag;
       
  1863 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
  1864 public: // GCC doesn't compile CIp6InterfaceLinkage, if this is private! -- msa
       
  1865     RTimeout iTimeout;          //< Hook to the timer service (MTimeoutManager)
       
  1866     };
       
  1867 
       
  1868 //
       
  1869 //  CIp6InterfaceTimeoutLinkage
       
  1870 //  ***********************
       
  1871 //  Glue to bind timeout callback from the timeout manager into Timeout() call
       
  1872 //  on the CIp6Route
       
  1873 //
       
  1874 //  *NOTE*
       
  1875 //      This kludgery is all static and compile time, and only used in the constructor
       
  1876 //      of CIp6Interface.
       
  1877 //
       
  1878 
       
  1879 // This ungainly manoevure is forced on us because the offset is not evaluated early enough by GCC3.4 to be
       
  1880 // passed as a template parameter
       
  1881 #if defined(__X86GCC__) || defined(__GCCE__)
       
  1882 #define KIp6InterfaceTimeoutOffset 696
       
  1883 __ASSERT_COMPILE(KIp6InterfaceTimeoutOffset == _FOFF(CIp6Interface, iTimeout));
       
  1884 #else
       
  1885 #define KIp6InterfaceTimeoutOffset _FOFF(CIp6Interface, iTimeout)
       
  1886 #endif
       
  1887 
       
  1888 class CIp6InterfaceTimeoutLinkage : public TimeoutLinkage<CIp6Interface, KIp6InterfaceTimeoutOffset>
       
  1889     {
       
  1890 public:
       
  1891     static void Timeout(RTimeout &aLink, const TTime &aNow, TAny * /*aPtr*/)
       
  1892         {
       
  1893         LOG(Log::Printf(_L("<>\tIF Timeout")));
       
  1894         Object(aLink)->Timeout(aNow);
       
  1895         }
       
  1896     };
       
  1897 
       
  1898 //
       
  1899 //  *********
       
  1900 //  CIp6Route
       
  1901 //  *********
       
  1902 //      Map address to specific gateway and interface
       
  1903 //
       
  1904 
       
  1905 // The main type of the route is expressed with 2 bits. However, in some
       
  1906 // cases system may need routes that are distinguished in GetRoute as
       
  1907 // distinct entries, but work the same everywhere else. Only one bit
       
  1908 // is reserved for that purpose now... (and used by ERedirect)
       
  1909 const TUint KRouteAdd_EXTENSIONMASK = (1 << 2);
       
  1910 const TUint KRouteAdd_SHIFT = 3;
       
  1911 
       
  1912 class CIp6Route : public CBase
       
  1913     {
       
  1914     friend class CIp6Flow;
       
  1915     friend class CIp6Manager;
       
  1916     friend class CIp6Interface;
       
  1917     friend class CIp6NifUser;
       
  1918     friend class CIp6RouteTimeoutLinkage;
       
  1919 public:
       
  1920     CIp6Route(TUint aIndex, CIp6Manager &aMgr, const TIp6Addr &aAddr, TInt aPrefix, CIp6Interface &aInterface);
       
  1921     ~CIp6Route();
       
  1922     TInt Match(const TIp6Addr &aAddr) const;
       
  1923     void Attach(CIp6Flow &aFlow);   //
       
  1924     void Attach(CIp6Route &aRoute); // "Steal" all flows from another route
       
  1925     void Detach(CIp6Flow &aFlow);
       
  1926     void NotifyFlows(TInt aStatus);
       
  1927     TInt SetChanged(const TInt aScope = 0) const;       // Set iChanged on attached flows
       
  1928 
       
  1929     enum TState
       
  1930         {
       
  1931         //
       
  1932         // The first 4 states must *exactly* match the route type
       
  1933         // value of the flags parameter in AddRouteL method!
       
  1934         //
       
  1935         // New CIp6Route can be created only into these 4 states
       
  1936         //
       
  1937         EIncomplete = KRouteAdd_NEIGHBOR,   //< == 0 (MUST BE ZERO)
       
  1938         ELoopback = KRouteAdd_MYPREFIX,     //< == 1
       
  1939         EOnlink = KRouteAdd_ONLINK,         //< == 2
       
  1940         EGateway = KRouteAdd_GATEWAY,       //< == 3
       
  1941         /**
       
  1942         // ERedirect is a special variant of a Gateway generated by
       
  1943         // the ICMP Redirects (mostly works exactly as a gateway)
       
  1944         */
       
  1945         ERedirect = KRouteAdd_EXTENSIONMASK | KRouteAdd_GATEWAY,
       
  1946         // EAnycast is a special variant of a Loopback enty
       
  1947         EAnycast = KRouteAdd_EXTENSIONMASK | KRouteAdd_MYPREFIX,
       
  1948         // The remaining states are only entered from EIncomplete
       
  1949         // if Neighbor discovery is applicable for the interface
       
  1950         // (all of these must have the low 2 bits zero, to
       
  1951         // make all of them as host routes (Type() == 0).
       
  1952         //
       
  1953         EReachable = 1 << KRouteAdd_SHIFT,
       
  1954         EStale =  2 << KRouteAdd_SHIFT,
       
  1955         EDelay = 3 << KRouteAdd_SHIFT,
       
  1956         EProbe = 4 << KRouteAdd_SHIFT,
       
  1957 
       
  1958         // A unique state for the fixed HoldingRoute
       
  1959         EHolding = 7 << KRouteAdd_SHIFT
       
  1960         };
       
  1961 
       
  1962     TUint ExtendedType() const
       
  1963         {
       
  1964         return iState & (KRouteAdd_EXTENSIONMASK | KRouteAdd_TYPEMASK);
       
  1965         }
       
  1966 
       
  1967     TUint Type() const
       
  1968         {
       
  1969         return iState & KRouteAdd_TYPEMASK;
       
  1970         }
       
  1971     TBool IsHoldingRoute() const
       
  1972         {
       
  1973         return iState == EHolding;
       
  1974         }
       
  1975     inline TBool IsOnlink() const
       
  1976         /** Matching address(es) is/are Onlink */
       
  1977         {
       
  1978         return Type() == KRouteAdd_ONLINK;
       
  1979         }
       
  1980     inline TBool IsGateway() const
       
  1981         /** Matching addresses should be sent to the gateway. */
       
  1982         {
       
  1983         return Type() == KRouteAdd_GATEWAY;
       
  1984         }
       
  1985     inline TBool IsHostRoute() const
       
  1986         /** Matching address is onlink with specified link layer address. */
       
  1987         {
       
  1988         return Type() == KRouteAdd_NEIGHBOR;
       
  1989         }
       
  1990     inline TBool IsMyPrefix() const
       
  1991         {
       
  1992         return iState == ELoopback && !iIsMulticast; // Note: Does no match EAnycast!
       
  1993         }
       
  1994     void Timeout(const TInt aExpired = 0);
       
  1995     //
       
  1996     // Accessing the main components uniformly independent of the class
       
  1997     // (when linkages between classes change, just change these to reflect
       
  1998     // the change, and the rest of the code should work unchanged)
       
  1999     //
       
  2000     inline CIp6Manager &Interfacer() const { return iInterfacer; };
       
  2001     //
       
  2002     // Set/reset a timer event on the current object
       
  2003     //
       
  2004     void SetTimer(TUint32 aDelay) { Interfacer().SetTimer(iTimeout, aDelay); }
       
  2005     // CancelTimer/IsTimerActive are just syntactic sugar, because
       
  2006     // of the SetTimer: if one uses SetTimer and hides iTimeout, then
       
  2007     // all uses of iTimeout should be "hidden" too!
       
  2008     inline void CancelTimer() { iTimeout.Cancel(); }
       
  2009     inline TBool IsTimerActive() { return iTimeout.IsActive(); }
       
  2010 #ifdef _LOG
       
  2011     const TDesC &LogRouteType() const;
       
  2012     //
       
  2013     // Generate a log message from current route state
       
  2014     //
       
  2015     void LogRoute(const TLifetime aLifetime) const;
       
  2016 #endif
       
  2017 
       
  2018 private:
       
  2019     const TUint iIndex;         //< Assigned Route index (always > 0)
       
  2020     CIp6Manager &iInterfacer;   //< The interface Manager
       
  2021     //
       
  2022     // The "address/prefix"
       
  2023     //
       
  2024     TIp6Addr iPrefix;           //< Address prefix for this route
       
  2025     TUint8 iLength;             //< Length of the prefix (bits)
       
  2026     TState iState:8;            //< Current State
       
  2027     TUint iRetry:8;             //< Tracks various retransmissions (depend on iState)
       
  2028     TUint iIsMulticast:1;       //< True if prefix is multicast address (precomputed for optim.)
       
  2029     TUint iIsRouter:1;          //< = 0, no other route may point to this (iRouter)
       
  2030     TUint iIsProbing:1;         //< = 1, if is probing route (not found by FindRoute)
       
  2031     TInt iMetric;               //< Metric value of the route (smaller is better)
       
  2032     TUint iTimeStamp;           //< Interpretation depends on iState
       
  2033     RMBufChain iPacket;         //< A packet waiting for ND completion, if any.
       
  2034 public: // GCC doesn't compile CIp6RouteLinkage, if this is private! -- msa
       
  2035     RTimeout iTimeout;          //< Hook to the timer service (MTimeoutManager)
       
  2036 private:
       
  2037     TInt Send(RMBufChain& aPacket, CProtocolBase* aSourceProtocol=NULL, TInt aMulticastLoop = 0);
       
  2038     void StartND(const TIp6Addr &aSrc);
       
  2039     TInt Update(TInt aFlags, const TSockAddr *aGateway, const TLifetime *const aLifetime);
       
  2040     void UpdatePrefix(const TLifetime aLifetime, const TLifetime aPreferred);
       
  2041     
       
  2042     void FillRouteInfo(TInetRouteInfo &rinfo, TLifetime aRefTime) const;
       
  2043     void FillNeighbourInfo(TInetNeighbourInfo &nginfo, TLifetime aRefTime) const;
       
  2044 
       
  2045     struct TIp6LifetimeField
       
  2046         {
       
  2047         TLifetime iStored;      //< Stored Lifetime (relative to interface startup)
       
  2048         TLifetime iPreferred;   //< "deprecated lifetime" in seconds
       
  2049         TUint iDeprecated:1;    //< = 1, when in "deprecated state"
       
  2050         TUint iCount;           //< Only used for multicast entries (for now)
       
  2051     };
       
  2052     
       
  2053     union
       
  2054         {
       
  2055         //
       
  2056         // Type() != ELoopback
       
  2057         //
       
  2058         // Note: Cannot use TSockAddr derived class, as it would generate a
       
  2059         // constructor and cannot use it here (inside union) -- msa 
       
  2060         //
       
  2061         TRouteAddress iAddress;
       
  2062         //
       
  2063         // Type() == ELoopback
       
  2064         //
       
  2065         TIp6LifetimeField iLifetime;
       
  2066         };
       
  2067     CIp6Route *iRouter;             //< Link to the Router entry, when it exists
       
  2068     //
       
  2069     // Linking of all routes on the interface
       
  2070     //
       
  2071     CIp6Interface &iInterface;      //< Interface definition
       
  2072     CIp6Route *iNext;               //< Route List Link (head in CIp6Interface)
       
  2073     CIp6Flow *iFlowList;            //< Book keeping of flows using this route
       
  2074     };
       
  2075 
       
  2076 //
       
  2077 //  CIp6RouteTimeoutLinkage
       
  2078 //  ***********************
       
  2079 //  Glue to bind timeout callback from the timeout manager into Timeout() call
       
  2080 //  on the CIp6Route
       
  2081 //
       
  2082 //  *NOTE*
       
  2083 //      This kludgery is all static and compile time, and only used in the constructor
       
  2084 //      of CIp6Route following this.
       
  2085 //
       
  2086 
       
  2087 // This ungainly manoevure is forced on us because the offset is not evaluated early enough by GCC3.4 to be
       
  2088 // passed as a template parameter
       
  2089 #if defined(__X86GCC__) || defined(__GCCE__)
       
  2090 #define KIp6RouteTimeoutOffset 44
       
  2091 __ASSERT_COMPILE(KIp6RouteTimeoutOffset == _FOFF(CIp6Route, iTimeout));
       
  2092 #else
       
  2093 #define KIp6RouteTimeoutOffset _FOFF(CIp6Route, iTimeout)
       
  2094 #endif
       
  2095 
       
  2096 class CIp6RouteTimeoutLinkage : public TimeoutLinkage<CIp6Route, KIp6RouteTimeoutOffset>
       
  2097     {
       
  2098 public:
       
  2099     static void Timeout(RTimeout &aLink, const TTime & /*aNow*/, TAny * /*aPtr*/)
       
  2100         {
       
  2101         LOG(Log::Printf(_L("<>\tROUTE Timeout")));
       
  2102         Object(aLink)->Timeout(1);  // aExpired==1 to signal true expiration
       
  2103         }
       
  2104     };
       
  2105 
       
  2106 //
       
  2107 //  TFlowOptions
       
  2108 //  ************
       
  2109 //  A dubious collection of fields that are mainly set
       
  2110 //  by set options.
       
  2111 //
       
  2112 class TFlowOptions
       
  2113     {
       
  2114 public:
       
  2115     TInt16 iHopLimit;           //< Hoplimit/TTL for non-multicast packets
       
  2116     TInt16 iMulticastHops;      //< Hoplimit/TTL for multicast packets
       
  2117     TUint8 iTrafficClass;       //
       
  2118     TUint iDF:1;
       
  2119     TUint iMulticastLoop:1;     //< 0=Don't loopback multicasts, 1=do loopback
       
  2120     // The interface flow count controls the NIF OpenRoute/CloseRoute calls,
       
  2121     // iKeepInterfaceUp controls whether this flow affects that count (the
       
  2122     // default is 0).
       
  2123     TUint iKeepInterfaceUp:1;   //< 0=Don't count, 1= count flow against inteface flow count
       
  2124 
       
  2125     // Note! Cannot use TScopeType below, because it would make the
       
  2126     // bitfield into signed and fail on tests like:
       
  2127     //      x.iLockType == EScopeType_NET
       
  2128     // even if x.iLockType has value EScopeType_NET!!! -- msa
       
  2129     /**
       
  2130     * Locked scope-1 (0..15) [TScopeType].
       
  2131     * Initialized from upper layer value at the beginning of the
       
  2132     * Connect. Cleared after use and must be "reactivated" by
       
  2133     * the hook, if it needs it. [No API this exists now]
       
  2134     */
       
  2135     TUint iLockType:4;
       
  2136     /**
       
  2137     * Current Locking Id.
       
  2138     * Initialized from upper layer value at the beginning of the
       
  2139     * Connect. Cleared after use and must be "reactivated" by
       
  2140     * the hook, if it needs it. [No API this exists now]
       
  2141     */
       
  2142     TUint32 iLockId;
       
  2143     };
       
  2144 
       
  2145 //  *********
       
  2146 //  TListLink
       
  2147 //  *********
       
  2148 class TListLink
       
  2149     /**
       
  2150     * A base class of a simple double linked list.
       
  2151     *
       
  2152     * This implmentain does not require the 'offset' like TDblQueBase.
       
  2153     * Also, NULL is never used, links are always non-NULL and if list
       
  2154     * is empty (or element is not part of any list),
       
  2155     * the links point to self.
       
  2156     *
       
  2157     * At this level, there is no difference between list head and
       
  2158     * an element.
       
  2159     */
       
  2160     {
       
  2161 public:
       
  2162     inline TListLink()
       
  2163         /**
       
  2164         * Constructor.
       
  2165         *
       
  2166         * TListLink is automaticly created as "detached", linked to self.
       
  2167         */
       
  2168         {
       
  2169         iPrev = this;
       
  2170         iNext = this;
       
  2171         }
       
  2172     inline ~TListLink()
       
  2173         /**
       
  2174         * Desctructor.
       
  2175         *
       
  2176         * TListLink(s) can be declared as a member of any class
       
  2177         * and there is no need to worry about instance being a
       
  2178         * member of lists when it is destroyed. This destructor
       
  2179         * automaticly removes the instance from a list if inserted.
       
  2180         */
       
  2181         {
       
  2182         Detach();
       
  2183         }
       
  2184     inline void MoveTo(TListLink &aList)
       
  2185         /**
       
  2186         * Move element to another list.
       
  2187         *
       
  2188         * MoveTo removes this element from previous list (if any)
       
  2189         * and inserts it to a new list, in front of the specified
       
  2190         * element (aList).
       
  2191         */
       
  2192         {
       
  2193         // Does not work if moving to self!
       
  2194         ASSERT(this != &aList);
       
  2195         if (this == &aList)
       
  2196             return;
       
  2197 
       
  2198         // Remove element from the old queue
       
  2199         iPrev->iNext = iNext;
       
  2200         iNext->iPrev = iPrev;
       
  2201         // Add to aList
       
  2202         iNext = &aList;
       
  2203         iPrev = aList.iPrev;
       
  2204         iPrev->iNext = this;
       
  2205         iNext->iPrev = this;
       
  2206         }
       
  2207 
       
  2208     inline void Detach()
       
  2209         /** Detach this element from a list (if any). */
       
  2210         {
       
  2211         iPrev->iNext = iNext;
       
  2212         iNext->iPrev = iPrev;
       
  2213         iNext = this;
       
  2214         iPrev = this;
       
  2215         }
       
  2216 
       
  2217 protected:
       
  2218     TListLink *iPrev;
       
  2219     TListLink *iNext;
       
  2220     };
       
  2221 
       
  2222 
       
  2223 //  ********
       
  2224 //  CIp6Flow
       
  2225 //  ********
       
  2226 //
       
  2227 class TFlowNotifyList;
       
  2228 class CIp6Flow : public CFlowInternalContext
       
  2229     {
       
  2230     friend class CIp6Manager;
       
  2231     friend class CIp6Route;
       
  2232     friend class CIp6Interface;
       
  2233     friend class CIp6NifUser;
       
  2234     friend class TFlowNotifyList;
       
  2235 public:
       
  2236     CIp6Flow(const void *aOwner, MFlowManager *aManager, CIp6Manager &aInterfacer, TUint aProtocol);
       
  2237     CIp6Flow(const void *aOwner, MFlowManager *aManager, CIp6Manager &aInterfacer, CFlowContext &aFlow);
       
  2238     virtual ~CIp6Flow();
       
  2239     virtual MInterfaceManager *Interfacer() const
       
  2240         { return &iInterfacer; }
       
  2241     virtual CNifIfBase *Interface() const;
       
  2242     virtual TInt Send(RMBufChain& aPacket, CProtocolBase* aSourceProtocol=NULL);
       
  2243     virtual void RefreshFlow();
       
  2244     virtual void Connect();
       
  2245     virtual TInt RouteFlow(TPacketHead &aHead);
       
  2246     virtual void Disconnect();
       
  2247     virtual TInt InterfaceSMtu() const;
       
  2248     virtual TInt InterfaceRMtu() const;
       
  2249     virtual TInt GetOption(TUint aLevel, TUint aName, TDes8 &aOption) const;
       
  2250     virtual TInt SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption);
       
  2251 
       
  2252     void Notify(TFlowNotifyList &aList, const TInt aState);
       
  2253     TInt SetChanged(const TInt aScope = 0); // Set iChanged
       
  2254 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
  2255     virtual TBool IsNdPacketPendingResolution();//RFC 4861 Changes
       
  2256 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
  2257 private:
       
  2258     TInt VerifyAddress(const TPacketHead &aHead, const CIp6Interface &aIf) const;
       
  2259     void SelectNextHop();
       
  2260 
       
  2261 #ifdef SYMBIAN_NETWORKING_UPS
       
  2262     TBool UPSPromptingPossible();
       
  2263     TBool ApplyStaticSecurityCheck();
       
  2264 #endif
       
  2265     CIp6Manager &iInterfacer;       // (i) Interface Manager
       
  2266     CIp6Route *iRoute;              // (i) Attached route
       
  2267     CIp6Flow *iNext;                // (i) Other flows on same route
       
  2268     TFlowOptions iOptions;          // (m)
       
  2269     TUint iSequence;                // (-) Used to detect expired source address.
       
  2270     TUint iTimeStamp;               // (-) Currently, only used when in HoldingRoute
       
  2271     TListLink iNotifyList;
       
  2272 #ifdef SYMBIAN_NETWORKING_UPS
       
  2273     TBool iUpsAuthorisationRequired;
       
  2274     TBool iUpsAuthorisationPending;
       
  2275 #endif
       
  2276     };
       
  2277 
       
  2278 
       
  2279 #ifdef _LOG
       
  2280 
       
  2281 //
       
  2282 // Internal utility to return a symbolic scope level name
       
  2283 // (only for DEBUG compile)
       
  2284 static const TDesC &LogScopeName(TInt aScope)
       
  2285     {
       
  2286     _LIT(KScope_0, "IF");       // 1 interface (node local)
       
  2287     _LIT(KScope_1, "IAP");      // 2 link local
       
  2288     _LIT(KScope_2, "SC3");      // 3
       
  2289     _LIT(KScope_3, "SC4");      // 4
       
  2290     _LIT(KScope_4, "SITE");     // 5 site local
       
  2291     _LIT(KScope_5, "SC6");      // 6
       
  2292     _LIT(KScope_6, "SC7");      // 7
       
  2293     _LIT(KScope_7, "ORG");      // 8 organization
       
  2294     _LIT(KScope_8, "SC9");      // 9
       
  2295     _LIT(KScope_9, "SC10");     // 10
       
  2296     _LIT(KScope_10, "SC11");    // 11
       
  2297     _LIT(KScope_11, "SC12");    // 12
       
  2298     _LIT(KScope_12, "SC13");    // 13
       
  2299     _LIT(KScope_13, "GBL");     // 14 global
       
  2300     _LIT(KScope_14, "SC15");    // 15
       
  2301     _LIT(KScope_15, "NET");     // -- network
       
  2302 
       
  2303     // Some tricky type casting is required to get rid of the
       
  2304     // writable static data problem at target linking...
       
  2305 #   define CAST(x) &reinterpret_cast<const TDesC &>(x)
       
  2306     static const TDesC *const map[] = 
       
  2307         {
       
  2308         CAST(KScope_0), CAST(KScope_1), CAST(KScope_2), CAST(KScope_3),
       
  2309         CAST(KScope_4), CAST(KScope_5), CAST(KScope_6), CAST(KScope_7),
       
  2310         CAST(KScope_8), CAST(KScope_9), CAST(KScope_10), CAST(KScope_11),
       
  2311         CAST(KScope_12), CAST(KScope_13), CAST(KScope_14), CAST(KScope_15)
       
  2312         };
       
  2313 #   undef CAST
       
  2314 
       
  2315 
       
  2316     return *map[aScope & 0xF];
       
  2317     }
       
  2318 
       
  2319 
       
  2320 //
       
  2321 // Internal utility for formatting address/prefix. Only for DEBUG compile
       
  2322 //
       
  2323 class TLogAddressPrefix : public TBuf<70>
       
  2324     {
       
  2325 public:
       
  2326     TLogAddressPrefix() {}
       
  2327     /** Format plain address%scope. */
       
  2328     TLogAddressPrefix(const TIp6Addr &aAddr);
       
  2329     /** Format address%scope/prefix. */
       
  2330     TLogAddressPrefix(const TIp6Addr &aAddr, const TInt aPrefix);
       
  2331     /** Format address%scope#port */
       
  2332     TLogAddressPrefix(const TInetAddr &aAddr);
       
  2333     /** Format plain address%scope. */
       
  2334     void Set(const TIp6Addr &aAddr);
       
  2335     /** Format address%scope/prefix. */
       
  2336     void Set(const TIp6Addr &aAddr, const TInt aPrefix);
       
  2337     /** Format address%scope#port */
       
  2338     void Set(const TInetAddr &aAddr);
       
  2339     };
       
  2340 
       
  2341 TLogAddressPrefix::TLogAddressPrefix(const TIp6Addr &aAddr)
       
  2342     {
       
  2343     Set(aAddr);
       
  2344     }
       
  2345 
       
  2346 TLogAddressPrefix::TLogAddressPrefix(const TIp6Addr &aAddr, const TInt aPrefix)
       
  2347     {
       
  2348     Set(aAddr, aPrefix);
       
  2349     }
       
  2350 
       
  2351 TLogAddressPrefix::TLogAddressPrefix(const TInetAddr &aAddr)
       
  2352     {
       
  2353     Set(aAddr);
       
  2354     }
       
  2355 
       
  2356 void TLogAddressPrefix::Set(const TIp6Addr &aAddr)
       
  2357     {
       
  2358     const TInetAddr addr(aAddr, 0);
       
  2359     addr.OutputWithScope(*this);
       
  2360     }
       
  2361 
       
  2362 void TLogAddressPrefix::Set(const TIp6Addr &aAddr, const TInt aPrefix)
       
  2363     {
       
  2364     Set(aAddr);
       
  2365     _LIT(KFormat, "/%d");
       
  2366     // Note: the overflow check is omitted on purpose (because
       
  2367     // leaving information out silently would cause more confusion).
       
  2368     // The supplied buffer should always be sufficient.
       
  2369     AppendFormat(KFormat, aPrefix - (aAddr.IsV4Mapped() ? 96 : 0));
       
  2370     }
       
  2371 
       
  2372 void TLogAddressPrefix::Set(const TInetAddr &aAddr)
       
  2373     {
       
  2374     if (aAddr.Family() == KAfInet || aAddr.Family() == KAfInet6 || aAddr.Family() == KAFUnspec)
       
  2375         aAddr.OutputWithScope(*this);
       
  2376     else
       
  2377         {
       
  2378         // Assume some type of link layer address, dump octets as xx:xx:...
       
  2379         SetLength(0);
       
  2380         const TPtrC8 ptr = TLinkAddr::Cast(aAddr).Address();
       
  2381         const TInt N = ptr.Length();
       
  2382         if (N > 0)
       
  2383             {
       
  2384             AppendNum((TInt)ptr[0], EHex);
       
  2385             for (TInt i = 1; i < N; ++i)
       
  2386                 {
       
  2387                 Append(':');
       
  2388                 AppendNum((TInt)ptr[i], EHex);
       
  2389                 }
       
  2390             }
       
  2391         }
       
  2392     if (aAddr.Port())
       
  2393         {
       
  2394         _LIT(KFormat, "#%d");
       
  2395         AppendFormat(KFormat, aAddr.Port());
       
  2396         }
       
  2397     }
       
  2398 
       
  2399 void PktLog(const TDesC &aFormat, const RMBufPktInfo &aInfo, TUint aIndex, const TDesC &aName)
       
  2400     {
       
  2401     TLogAddressPrefix src(TInetAddr::Cast(aInfo.iSrcAddr));
       
  2402     TLogAddressPrefix dst(TInetAddr::Cast(aInfo.iDstAddr));
       
  2403     Log::Printf(aFormat, aIndex, &aName, aInfo.iProtocol, &src, &dst, aInfo.iLength);
       
  2404     }
       
  2405 
       
  2406 #endif
       
  2407 
       
  2408 
       
  2409 class TFlowNotifyList : public TListLink
       
  2410     {
       
  2411 public:
       
  2412     void Insert(CIp6Flow &aFlow);
       
  2413     void Deliver(TInt aStatus);
       
  2414     };
       
  2415 
       
  2416 
       
  2417 void TFlowNotifyList::Insert(CIp6Flow &aFlow)
       
  2418     {
       
  2419     aFlow.iNotifyList.MoveTo(*this);
       
  2420     }
       
  2421 
       
  2422 void TFlowNotifyList::Deliver(TInt aStatus)
       
  2423     {
       
  2424     TListLink *p;
       
  2425     while ((p = iNext) != this)
       
  2426         {
       
  2427         p->Detach();
       
  2428         CIp6Flow *const f = (CIp6Flow *)((TUint8 *)p - _FOFF(CIp6Flow, iNotifyList));
       
  2429 #ifdef _LOG
       
  2430             {
       
  2431             TLogAddressPrefix src(f->iInfo.iLocal);
       
  2432             TLogAddressPrefix dst(f->iInfo.iRemote);
       
  2433             Log::Printf(_L("\t\tFlow[%u] Deliver(%d -> %d) prot=%d src=[%S], dst=[%S]"),
       
  2434                 (TInt)f, aStatus, f->iStatus, (TInt)f->iInfo.iProtocol, &src, &dst);
       
  2435             }
       
  2436 #endif
       
  2437         f->SetStatus(aStatus);
       
  2438         }
       
  2439     }
       
  2440 
       
  2441 
       
  2442 
       
  2443 //
       
  2444 // Internal help utility to retrieve tick period as unsigned int
       
  2445 //
       
  2446 static TUint TickPeriod()
       
  2447     {
       
  2448     TTimeIntervalMicroSeconds32 period;
       
  2449     UserHal::TickPeriod(period);
       
  2450     return (TUint)period.Int();
       
  2451     }
       
  2452 
       
  2453 static TUint ElapsedUnits(const TTime &aMark, const TTime &aLater)
       
  2454     /**
       
  2455     * Internal help utitility to compute the difference between two timestamps.
       
  2456     *
       
  2457     * @param aMark  The earlier time stamp
       
  2458     * @param aLater The later time stamp
       
  2459     *
       
  2460     * @return
       
  2461     *   (aLater - aMark) in timer units, or KMaxTUint if
       
  2462     *   the value does not fit in TUint.
       
  2463     */
       
  2464     {
       
  2465     const TInt64 elapsed = aLater.MicroSecondsFrom(aMark).Int64() / (1000000 / TIMER_UNIT);
       
  2466 #ifdef I64HIGH
       
  2467     return I64HIGH(elapsed) != 0 ? KMaxTUint : I64LOW(elapsed);
       
  2468 #else
       
  2469     return elapsed.High() != 0 ? KMaxTUint : elapsed.Low();
       
  2470 #endif
       
  2471     }
       
  2472 
       
  2473 
       
  2474 // **********
       
  2475 // CIp6Daemon
       
  2476 // **********
       
  2477 class CIp6Daemon : public CBase
       
  2478     /**
       
  2479     * Keep track of active daemons related to the protocol stack
       
  2480     */
       
  2481     {
       
  2482 public:
       
  2483     ~CIp6Daemon();
       
  2484     void Start(const TDesC &aProcessName, const TDesC &aFileName);
       
  2485     void Kill();
       
  2486     CIp6Daemon *iNext;
       
  2487     RProcess iProcess;
       
  2488     TUint iStarted:1;   //< =1, if handle is attached to another process/thread
       
  2489     };
       
  2490 
       
  2491 // ***********
       
  2492 // ~CIp6Daemon
       
  2493 // ***********
       
  2494 CIp6Daemon::~CIp6Daemon()
       
  2495     /** Also automaticly kills the attached process, if any running. */
       
  2496     {
       
  2497     Kill();
       
  2498     }
       
  2499 
       
  2500 // ****************
       
  2501 // CIp6Daemon::Kill
       
  2502 // ****************
       
  2503 void CIp6Daemon::Kill()
       
  2504     /** Kill thread/process, if running and disconnect handle from the thread/process. */
       
  2505     {
       
  2506     if (iStarted)
       
  2507         {
       
  2508         iStarted = 0;
       
  2509         if (iProcess.ExitType() == EExitPending)
       
  2510             iProcess.Kill(KErrServerTerminated);
       
  2511         iProcess.Close();
       
  2512         }
       
  2513     }
       
  2514 
       
  2515 // *****************
       
  2516 // CIp6Daemon::Start
       
  2517 // *****************
       
  2518 //
       
  2519 void CIp6Daemon::Start(const TDesC &aProcessName, const TDesC &aFileName)
       
  2520     /** Start the named EXE as a daemon. */
       
  2521     {
       
  2522     ASSERT(!iStarted);
       
  2523 
       
  2524     TInt res = iProcess.Create(aFileName, _L(""));
       
  2525     if (res == KErrNone)
       
  2526         {
       
  2527         iStarted = 1;
       
  2528         iProcess.Resume();
       
  2529         }
       
  2530 
       
  2531 #ifdef _LOG
       
  2532     if (iStarted)
       
  2533         Log::Printf(_L("CIp6Daemon::Start(%S, %S) OK"), &aProcessName, &aFileName);
       
  2534     else
       
  2535         Log::Printf(_L("CIp6Daemon::Start(%S, %S) *** FAILED *** with error %d"), &aProcessName, &aFileName, res);
       
  2536 #else
       
  2537     (void)aProcessName; // prevent warning message
       
  2538 #endif
       
  2539     }
       
  2540 
       
  2541 // TIp6AddressInfo::Match
       
  2542 // **********************
       
  2543 TBool TIp6AddressInfo::Match(const TIp6Addr &aAddr) const
       
  2544     /**
       
  2545     * Match ID part.
       
  2546     *
       
  2547     * @param aAddr The id to compare with.
       
  2548     *
       
  2549     * Match returns TRUE, if aAddr matches the
       
  2550     * ID/hostnumber (tailored after similar code in
       
  2551     * TIp6Addr::Match() )
       
  2552     */
       
  2553     {
       
  2554     ASSERT(iPrefix <= 128);
       
  2555     if (iPrefix > 127)  // (actually, == 128)
       
  2556         return TRUE;
       
  2557 
       
  2558     TInt i = 3;
       
  2559     while (iId.u.iAddr32[i] == aAddr.u.iAddr32[i])
       
  2560         if (i == 0)
       
  2561             return TRUE;    // Obviously true, regardless of the iPrefix
       
  2562         else
       
  2563             --i;
       
  2564     // Optimize for 64 bit id?
       
  2565     // if (iPrefix >= 64 && i < 2) return TRUE;
       
  2566 
       
  2567     i = i * 2 + 1;
       
  2568     if (iId.u.iAddr16[i] == aAddr.u.iAddr16[i])
       
  2569         --i;
       
  2570 
       
  2571     i = i * 2 + 1;
       
  2572     if (iId.u.iAddr8[i] == aAddr.u.iAddr8[i])
       
  2573         --i;
       
  2574 
       
  2575     // i = index of the byte containing a difference, the
       
  2576     // number of unmatched bits is (i+1) * 8 - "matched bits
       
  2577     // in the current byte". ...count them below
       
  2578     //
       
  2579     TUint8 diff = (TUint8)(iId.u.iAddr8[i] ^ aAddr.u.iAddr8[i]);
       
  2580     for (i = (i + 1) << 3; !(diff & 0x1); diff >>= 1)
       
  2581         --i;
       
  2582     // Matched full id part?
       
  2583     return iPrefix >= i;
       
  2584     }
       
  2585 
       
  2586 // TIp6AddressInfo::MatchExactly
       
  2587 // **********************
       
  2588 TBool TIp6AddressInfo::MatchExactly(const TIp6Addr &aAddr) const
       
  2589     /**
       
  2590     * Match ID part only.
       
  2591     *
       
  2592     * @param aAddr The id to compare with.
       
  2593     *
       
  2594     * Match returns TRUE, if aAddr matches the
       
  2595     * ID/hostnumber (tailored after similar code in
       
  2596     * TIp6Addr::Match() )
       
  2597     */
       
  2598     {
       
  2599     ASSERT(iPrefix <= 128);
       
  2600 
       
  2601     // If any address bits are ignored, return false as the address
       
  2602      // cannot be an exact match.
       
  2603      if( iPrefix != 0 )
       
  2604          {
       
  2605          return EFalse;
       
  2606          }
       
  2607   
       
  2608     // Determine the size of the address.
       
  2609     TUint addrBits = sizeof( iId.u )/ sizeof( TUint );
       
  2610     TUint addrWords = addrBits;
       
  2611     if( iId.IsV4Mapped() )
       
  2612         {
       
  2613         addrWords = 1;
       
  2614         }
       
  2615     
       
  2616         
       
  2617     // Check every address word.
       
  2618     for( TUint i = ( addrBits ) - addrWords; i < addrBits; ++i )
       
  2619         {
       
  2620         if( aAddr.u.iAddr32[i] != iId.u.iAddr32[i] )
       
  2621             {
       
  2622             return EFalse;
       
  2623             }
       
  2624         }
       
  2625         
       
  2626     return ETrue;
       
  2627     }
       
  2628 
       
  2629 
       
  2630 // **********************************************
       
  2631 // CIp6Flow, the flow termination implementations
       
  2632 // **********************************************
       
  2633 
       
  2634 // 
       
  2635 // Interaface
       
  2636 // **********
       
  2637 // Return connected interface
       
  2638 CNifIfBase *CIp6Flow::Interface() const
       
  2639     {
       
  2640     //
       
  2641     // Is this flow actually connected?
       
  2642     //
       
  2643     if (iRoute)
       
  2644         return iRoute->iInterface.iNifIf;
       
  2645     else
       
  2646         return NULL;
       
  2647     }
       
  2648 
       
  2649 
       
  2650 //
       
  2651 //  CIp6Flow::CIp6Flow
       
  2652 //  ******************
       
  2653 //  *BEWARE*
       
  2654 //      iManager link is set here, but there is no path from
       
  2655 //      the manager to this until it is connected (after which
       
  2656 //      it can be found via routes). If manager is destroyed,
       
  2657 //      it is possible to have dangling pointers from
       
  2658 //      unconnected flows!
       
  2659 //
       
  2660 //      However, the current assumption is that all flows are
       
  2661 //      allocated within this same protocol library and all
       
  2662 //      them must have been deleted before the family object
       
  2663 //      and the associated CIp6Manager gets deleted.
       
  2664 //
       
  2665 //      The iFlows count in the CIp6Manager is maintained only
       
  2666 //      to catch programming errors (and a Panic is issued).
       
  2667 
       
  2668 CIp6Flow::CIp6Flow(const void *aOwner, MFlowManager *aManager, CIp6Manager &aInterfacer, TUint aProtocol)
       
  2669 : CFlowInternalContext(aOwner, aManager), iInterfacer(aInterfacer)
       
  2670     {
       
  2671     iInterfacer.iFlows++;
       
  2672     iInfo.iProtocol = (TUint8)aProtocol;
       
  2673     // Init with default "interface error handling" policy
       
  2674     iInfo.iNoInterfaceError = iInterfacer.iNoInterfaceError;
       
  2675     // By default, lock flows to any network
       
  2676     iInfo.iLockId = 0;
       
  2677     iInfo.iLockType = EScopeType_NET;
       
  2678     // Init default for flow counting on interfaces policy
       
  2679     iOptions.iKeepInterfaceUp = iInterfacer.iKeepInterfaceUp;
       
  2680     //
       
  2681     // Initialize non-zero defaults for options
       
  2682     //
       
  2683     iOptions.iHopLimit = -1;
       
  2684     iOptions.iMulticastHops = -1;
       
  2685     iOptions.iMulticastLoop = 1;
       
  2686     LOG(Log::Printf(_L("\t\tFlow[%u] New: protocol=%d (%d flows now)"), this, (TInt)aProtocol, iInterfacer.iFlows));
       
  2687     }
       
  2688 
       
  2689 CIp6Flow::CIp6Flow(const void *aOwner, MFlowManager *aManager, CIp6Manager &aInterfacer, CFlowContext &aFlow)
       
  2690 : CFlowInternalContext(aOwner, aManager, aFlow), iInterfacer(aInterfacer)
       
  2691     {
       
  2692     iInterfacer.iFlows++;
       
  2693     iInfo.iProtocol = (TUint8)aFlow.Protocol();
       
  2694     // Assumes below that the aFlow is also CIp6Flow!
       
  2695     iOptions = ((CIp6Flow &)aFlow).iOptions;
       
  2696     LOG(Log::Printf(_L("\t\tFlow[%u] New: protocol=%d cloning from Flow[%u] (%d flows now)"),
       
  2697         this, (TInt)iInfo.iProtocol, (TInt)&aFlow, iInterfacer.iFlows));
       
  2698     }
       
  2699 
       
  2700 CIp6Flow::~CIp6Flow()
       
  2701     {
       
  2702     //
       
  2703     // Detach flow from a route if connected
       
  2704     //
       
  2705     if (iRoute)
       
  2706         iRoute->Detach(*this);
       
  2707     ASSERT(iInterfacer.iFlows > 0);
       
  2708     iInterfacer.iFlows--;
       
  2709     LOG(Log::Printf(_L("\t\tFlow[%u] Deleted (%d flows remaining)"), this, iInterfacer.iFlows));
       
  2710     }
       
  2711 
       
  2712 
       
  2713 // CIp6Flow::Notify
       
  2714 // ****************
       
  2715 //
       
  2716 // *NOTE* The assumption here is that if the aState is negative, it
       
  2717 //        the error state of the interface (thus the test for
       
  2718 //        iNoInterfaceError is correct).
       
  2719 //
       
  2720 void CIp6Flow::Notify(TFlowNotifyList &aList, const TInt aState)
       
  2721     {
       
  2722     if (aState >= 0 || iInfo.iNoInterfaceError == 0)
       
  2723         aList.Insert(*this);
       
  2724     }
       
  2725 
       
  2726 // CIp6Flow::SetChanged
       
  2727 // ********************
       
  2728 TInt CIp6Flow::SetChanged(const TInt aScope)
       
  2729     {
       
  2730     if (aScope > 0)
       
  2731         return iRoute ? iRoute->SetChanged(aScope-1) : 0;
       
  2732     iChanged = 1;
       
  2733     // *NOTE* It might be convenient to call SetStatus(EFlow_READY),
       
  2734     // if iState is PENDING (> 0) to wake up the SAP. However, this
       
  2735     // might cause problems, because SetStatus() may cause a destruction
       
  2736     // of the flow context (and possibly other structures), and if this
       
  2737     // is called from CIp6Route instance or higher, then all traversing
       
  2738     // loops would need to be protected against destruction of any object
       
  2739     // on the list while processing the list... -- msa
       
  2740     return 1;
       
  2741     }
       
  2742 
       
  2743 //
       
  2744 //  CIp6Flow::Send
       
  2745 //  **************
       
  2746 TInt CIp6Flow::Send(RMBufChain& aPacket, CProtocolBase* aSrc)
       
  2747     /**
       
  2748     * Send a packet to the attached interface.
       
  2749     *
       
  2750     * @param aPacket    The packet.
       
  2751     * @param aSrc       The source (mostly ignored).
       
  2752     *
       
  2753     * @return
       
  2754     *   @li < 0, no interface of some other missing component
       
  2755     *   @li = 0, packet sent, but interface does not want more after this
       
  2756     *   @li = 1, packet sent, and interface is willing to accept more
       
  2757     *
       
  2758     *   The packet "ownership" is always transfered, regardless of the return type
       
  2759     *   (the aPacket should be empty after this!)
       
  2760     *
       
  2761     *   On entry, the packet must have a info structure of RMBufSendInfo.
       
  2762     *   This routine will release the flow handle, if any attached.
       
  2763     */
       
  2764     {
       
  2765     RFlowContext flow;
       
  2766     TInt ret = KErrNotReady;
       
  2767 
       
  2768     RMBufSendInfo *const info = RMBufSendPacket::PeekInfoInChain(aPacket);
       
  2769     if (info)
       
  2770         {
       
  2771         flow.Grab(info->iFlow);
       
  2772         ASSERT(flow.FlowContext() == this);
       
  2773         if (iRoute)
       
  2774             {
       
  2775             if (iSequence != iRoute->iInterface.iSequence)
       
  2776                 {
       
  2777                 // The valid address list has been changed since
       
  2778                 // the last packet, verify that the current source
       
  2779                 // address is still legal.
       
  2780                 // *NOTE* after ReadyL processing the iHead represents
       
  2781                 // the "upper layer view" of the addresses (for example,
       
  2782                 // there might be home addresses loaded with mobile-ip).
       
  2783                 // However, here the test need to be done on the ultimate
       
  2784                 // final addresses being used for each packet, and those
       
  2785                 // *SHOULD* *ALWAYS* be in the iStart, which is saved
       
  2786                 // after OpenL() phase! The test here must be done to
       
  2787                 // the final address!!! -- msa
       
  2788                 //
       
  2789                 ret = VerifyAddress(iStart, iRoute->iInterface);
       
  2790                 if (ret != KErrNone)
       
  2791                     {
       
  2792                     // Invalid address, shutdown the flow
       
  2793                     SetStatus(ret);
       
  2794                     goto drop_out;
       
  2795                     }
       
  2796                 // Prevent further tests until next address expiration
       
  2797                 iSequence = iRoute->iInterface.iSequence;
       
  2798                 }
       
  2799                             
       
  2800             // Because the flow has been detached from the packet, this
       
  2801             // is the last point where we can set the correct value for
       
  2802             // the KIpKeepInterfaceUp bit (which controls the counters
       
  2803             // for the NIF shutdown).
       
  2804             if (iOptions.iKeepInterfaceUp)
       
  2805                 info->iFlags |= KIpKeepInterfaceUp;     // Set
       
  2806             else
       
  2807                 info->iFlags &= ~KIpKeepInterfaceUp;    // Clear
       
  2808             ret = iRoute->Send(aPacket, aSrc, iOptions.iMulticastLoop);
       
  2809             }
       
  2810 drop_out:
       
  2811         flow.Close();   // <-- May delete THIS? (Probably, if above KErrInet6AddressExpired occurred!)
       
  2812         }
       
  2813     aPacket.Free();     // NOOP, if already done or assigned to elsewhere
       
  2814     return ret;
       
  2815     }
       
  2816 
       
  2817 TInt CIp6Flow::VerifyAddress(const TPacketHead &aHead, const CIp6Interface &aIf) const
       
  2818     /**
       
  2819     * Verify that the current source address is valid for the interface.
       
  2820     *
       
  2821     * For forwarding flows only, the source address scope is verified. The forwarding
       
  2822     * flows are allowed to use "invalid source addresses". The source address of other
       
  2823     * flows must be either unspecified address or a configured and assigned address on
       
  2824     * the interface.
       
  2825     *
       
  2826     * @return
       
  2827     *   @li KErrNone, if valid
       
  2828     *   @li KErrInet6SourceAddress, if address is out of scope
       
  2829     *   @li KErrInet6AddressExpired, if address is missing.
       
  2830     */
       
  2831     {
       
  2832     const TIp6Addr &src = aHead.ip6.SrcAddr();
       
  2833 
       
  2834     //
       
  2835     // Verify the source address in a aHead
       
  2836     //
       
  2837     const TUint scope = (TUint)(src.Scope() - 1);
       
  2838     if (!TIp46Addr::Cast(src).IsUnspecified())
       
  2839         {
       
  2840         if (scope > EScopeType_NET || aHead.iSrcId != aIf.iScope[scope])
       
  2841             {
       
  2842             // Trying to use out of scope source address
       
  2843             return KErrInet6SourceAddress;
       
  2844             }
       
  2845 #ifndef WEAK_ES
       
  2846         // In strong ES model, don't allow sending packets
       
  2847         // with wrong source address (except unspecified address
       
  2848         // in some rare cases, and if we are forwarding data).
       
  2849         if (iInfo.iForwardingFlow == 0 && aIf.IsMyAddress(src) == NULL)
       
  2850             {
       
  2851             return KErrInet6AddressExpired;
       
  2852             }
       
  2853 #endif
       
  2854         }
       
  2855     return KErrNone;
       
  2856     }
       
  2857 
       
  2858 //
       
  2859 // CIp6Flow::RefreshFlow
       
  2860 // *********************
       
  2861 void CIp6Flow::RefreshFlow()
       
  2862     /**
       
  2863     * Recompute the current flow status.
       
  2864     *
       
  2865     * This function is called when a flow in needed and the status is > 0 (pending or hold).
       
  2866     * This checks whether the flow can be changed into ready state, and it (re)runs the
       
  2867     * MIp6Hook::ReadyL phase for the hooks.
       
  2868     */
       
  2869     {
       
  2870     if (iChanged)
       
  2871         {
       
  2872         LOG(Log::Printf(_L("\t\tFlow[%u] Changed, reconnect required"), this));
       
  2873         return;
       
  2874         }
       
  2875     if (!iRoute)
       
  2876         {
       
  2877         iStatus = KErrNotFound;     // No route available/attached!
       
  2878         LOG(Log::Printf(_L("\t\tFlow[%u] No route"), this));
       
  2879         return;
       
  2880         }
       
  2881 
       
  2882     CIp6Interface &iface = iRoute->iInterface;
       
  2883     if (iface.iState != EFlow_READY)
       
  2884         {
       
  2885         LOG(Log::Printf(_L("\t\tFlow[%u] %S is not ready (%d)"), this, &iface.iName, iface.iState));
       
  2886         iStatus = iface.iState == EFlow_HOLD ? EFlow_HOLD : EFlow_PENDING;
       
  2887         return;
       
  2888         }
       
  2889 
       
  2890     Reset();
       
  2891     const TIp6Addr &dst = iHead.ip6.DstAddr();
       
  2892     // For log prints, have destination address as a string.
       
  2893     LOG(TLogAddressPrefix log_dst(dst));
       
  2894     ASSERT(iHead.iSourceSet);
       
  2895     iStatus = VerifyAddress(iHead, iface);
       
  2896     if (iStatus < 0)
       
  2897         return;
       
  2898     iSequence = iRoute->iInterface.iSequence;   // Address in synch for now!
       
  2899 
       
  2900     iTimeStamp = 0; // [for why, look at comments in MoveToHolding!! -- msa]
       
  2901     //
       
  2902     // This destination will be needed, thus activate ND, if destination is not yet
       
  2903     // known! (note: at this point the ultimate src address of the packet is already
       
  2904     // known.
       
  2905     CIp6Route *const host_route = iRoute->iRouter ? iRoute->iRouter : iRoute;
       
  2906     if (host_route->iState == CIp6Route::EIncomplete)
       
  2907         {
       
  2908         LOG(Log::Printf(_L("\t\tFlow[%u] IF %u [%S] Next hop address not known, start ND [%S]"), this, iface.iScope[0], &iface.iName, &log_dst));
       
  2909         host_route->StartND(iHead.ip6.SrcAddr());
       
  2910         }
       
  2911     //
       
  2912     // The Path MTU is *ALWAYS* maintained to have some sensible
       
  2913     // value. Use it as is.
       
  2914     //
       
  2915     // 1) Check whether destination cache has a stored path mtu entry
       
  2916     //      cachemtu == 0, if dstcache is not enabled or entry was not found in the cache
       
  2917     // 2) If not, use value stored with interface
       
  2918     const TUint cachemtu = iInterfacer.GetDstCachePathMtu(dst, iHead.iDstId);
       
  2919     if (cachemtu && (iPathMtu == 0 || iPathMtu > cachemtu))
       
  2920         iPathMtu = cachemtu;
       
  2921     else if (iPathMtu == 0 || (TInt)iPathMtu > iface.iPMtu)
       
  2922         iPathMtu = iface.iPMtu; // Just copy current Path MTU from the interface
       
  2923 
       
  2924     if (iPathMtu > 0)
       
  2925         {
       
  2926         // Choose framing purely on whether destination is is
       
  2927         // IPv4 mapped (=> do IPv4) or not (=> do IPv6).
       
  2928         iHead.ip6.SetVersion(dst.IsV4Mapped() ? 4 : 6); 
       
  2929         if (iHead.ip6.HopLimit() != iface.iHopLimit)
       
  2930             {
       
  2931             // The current hoplimit differs from the interface default. This
       
  2932             // can happen for following reasons:
       
  2933             // - hoplimit has not yet been initialize (still has value 0)
       
  2934             // - destination is multicast (the default is different)
       
  2935             // - hoplimit has been overriden by socket option
       
  2936             // - hoplimit on interface has changed due to RA
       
  2937             //
       
  2938             // The following assigns a value to hoplimit. This will get
       
  2939             // unnecessarily executed for each refresh, if hoplimit is
       
  2940             // set by socket option or destination is multicast. However,
       
  2941             // this should not cause too much overhead, as refresh is not
       
  2942             // supposed to happen frequently on every packet!
       
  2943             //
       
  2944             // Doing it in this way (comparing the limit to to interface), has
       
  2945             // the advantage that if RA changes the default for the interface,
       
  2946             // it will take effect on flows at next refresh (otherwise, RA
       
  2947             // processing would need to force "iChanged" on all flows to get
       
  2948             // it effective) -- still may have to do it that way, but first
       
  2949             // this solution is tested if it will be sufficient -- msa
       
  2950             //
       
  2951             if (TIp46Addr::Cast(dst).IsMulticast())
       
  2952                 iHead.ip6.SetHopLimit(iOptions.iMulticastHops < 0 ? 1 : iOptions.iMulticastHops);
       
  2953             else if (iOptions.iHopLimit >= 0)   // override by socket option?
       
  2954                 iHead.ip6.SetHopLimit(iOptions.iHopLimit);
       
  2955 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
  2956             // According to RFC 4861, Echo Reply needs to respond with CurHopLimit set earlier by RA
       
  2957             //else if (TIp46Addr::Cast(dst).IsLinkLocal() && iface.Interfacer().iLinkLocalTTL >= 0)
       
  2958                 //iHead.ip6.SetHopLimit(iface.Interfacer().iLinkLocalTTL);
       
  2959 #else
       
  2960             else if (TIp46Addr::Cast(dst).IsLinkLocal() && iface.Interfacer().iLinkLocalTTL >= 0)
       
  2961             iHead.ip6.SetHopLimit(iface.Interfacer().iLinkLocalTTL);
       
  2962 #endif //SYMBIAN_TCPIPDHCP_UPDATE	
       
  2963             else
       
  2964                 iHead.ip6.SetHopLimit(iface.iHopLimit);
       
  2965             }
       
  2966         //
       
  2967         // Run the ReadyL phase for the flow
       
  2968         //
       
  2969 
       
  2970         RefreshHooks();                 // Set status from hooks
       
  2971         iMgr->FlowStartRefresh(*this);  // (this needs be done for inner header, if tunnels!)
       
  2972 
       
  2973         //
       
  2974         // If we already have a packet, we should make it possible to delay this.
       
  2975         // EFlow_PENDING is only meant for NIF startup and EFlow_HOLD for temporarily blokcs.
       
  2976         // Thus, for future this should something like EFlow_ROUTEHOLD = 3
       
  2977         // but to minimize regression with current hooks we use HOLD for now.
       
  2978         //
       
  2979         if (!iRoute->iPacket.IsEmpty())
       
  2980             SetStatus(EFlow_HOLD);
       
  2981         //
       
  2982         // If the upper layer has not specified the source address
       
  2983         // explicitly (iLocalSet TRUE), then the current source address
       
  2984         // from the iHead.ip6.SrcAddr() is copied for the upper layer.
       
  2985         // This is done *after* the hooks so that they have a chance to
       
  2986         // change it (for example, mobile IP with Care/Home Address).
       
  2987         //
       
  2988         // If a hook adds tunnel(s), it is the responsiblity of the hook
       
  2989         // to change the source in iHead to the inner source while
       
  2990         // doing the ReadyL() processing (upper layer will see the
       
  2991         // inner source!)
       
  2992         //
       
  2993         if (!iInfo.iLocalSet)
       
  2994             iInfo.iLocal.SetAddress(iHead.ip6.SrcAddr());
       
  2995         //
       
  2996         // Final scope id's are unconditionally set
       
  2997         // (for now)
       
  2998         iInfo.iLocal.SetScope(iHead.iSrcId);
       
  2999         iInfo.iRemote.SetScope(iHead.iDstId);
       
  3000         }
       
  3001     else
       
  3002         {
       
  3003         iStatus = KErrInet6NoPathMtu;
       
  3004         LOG(Log::Printf(_L("\t\tFlow[%u] IF %u [%S] has no MTU"), this, iface.iScope[0], &iface.iName));
       
  3005         }
       
  3006     }
       
  3007 
       
  3008 
       
  3009 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
  3010 // CIp6Flow::IsNdPacketPendingResolution ( RFC 4861 )
       
  3011 // Returns ETrue if empty else returns EFalse
       
  3012 // *********************
       
  3013 TBool CIp6Flow::IsNdPacketPendingResolution()
       
  3014     {
       
  3015     // CIP6Route Class holds information related to pending Neighbour Discovery packet waiting for Address resolution on that route
       
  3016     // This method returns ETrue if there are no pending packets
       
  3017     TBool ndPktExists = EFalse;
       
  3018     if (iRoute) //If Route Exists
       
  3019         {
       
  3020          if(!iRoute->iPacket.IsEmpty()) // Pending ND Packet exists
       
  3021              {
       
  3022              ndPktExists = ETrue;
       
  3023              return ndPktExists;
       
  3024              }
       
  3025          else   // Pending ND Packet doesnt exist
       
  3026              {
       
  3027              ndPktExists = EFalse;
       
  3028              return ndPktExists;
       
  3029              }
       
  3030         }
       
  3031     return ndPktExists;
       
  3032     }
       
  3033 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
  3034 
       
  3035 
       
  3036 // CIp6Flow::RouteFlow
       
  3037 // *******************
       
  3038 TInt CIp6Flow::RouteFlow(TPacketHead &aHead)
       
  3039     /**
       
  3040     * Route a flow to an interface based on a TPacketHead
       
  3041     *
       
  3042     * Using the current connection parameters in the given TPacketHead (aHead),
       
  3043     * try to locate an interface for the flow. If found, complete TPacketHead
       
  3044     * information from the selected interface. Verify the validity of the
       
  3045     * source address, if it is defined (TPacketHead::iSourceSet == 1), or try
       
  3046     * to select the source address otherwise.
       
  3047     *
       
  3048     * In addition to initial call in Connect(), the RouteFlow is called
       
  3049     * after each MIp6Hook::OpenL, if any the addressing information has been
       
  3050     * changed by the hook.
       
  3051     *
       
  3052     * @param    aHead   The connection parameters.
       
  3053     *
       
  3054     * @return A value for the flow status, as follows:
       
  3055     *   @li EFlow_READY, if routing succeeded and route attached
       
  3056     *   @li EFlow_PENDING, if route or source address cannot be selected
       
  3057     *   @li KErrInet6NoDestination, if destination address is missing
       
  3058     *   @li KErrInet6SourceAddress, if source address is out of scope
       
  3059     *   @li KErrInet6AddressExpired, if source address is not valid for the interface.
       
  3060     *   @li KErrInet6NoRoute, if route or source address cannot be selected and on demand setup is not desired.
       
  3061     *
       
  3062     * In case the route is not found, the function starts a neighbor probe for the
       
  3063     * destination address on all interfaces in the current scope (only if this
       
  3064     * feature is enabled via the configuration parameter or one or more interfaces
       
  3065     * have link local source addresses).
       
  3066     *
       
  3067     */ 
       
  3068     {
       
  3069     const TIp6Addr &dst = aHead.ip6.DstAddr();
       
  3070     TUint dstType = (TUint)(dst.Scope()-1);
       
  3071     if (dst.IsUnspecified() || dstType > EScopeType_NET)
       
  3072         return KErrInet6NoDestination;
       
  3073 
       
  3074     CIp6Route *rt = NULL;
       
  3075     for (;;) /* NOT A LOOP, JUST FOR BREAK EXITS */
       
  3076         {
       
  3077         // For "forwarding flows", the source address is set, but must not affect the
       
  3078         // route selection (because it would fail due to address not being a valid
       
  3079         // address for this host!). Need two temp locations to hold the source info.
       
  3080         const TInt use_source = aHead.iSourceSet && iInfo.iForwardingFlow == 0;
       
  3081         const TIp6Addr &src_tmp = use_source ? aHead.ip6.SrcAddr() : KInet6AddrNone;
       
  3082         const TUint32 src_id = use_source ? aHead.iSrcId : 0;
       
  3083 
       
  3084         if (aHead.iDstId == 0)
       
  3085             {
       
  3086             // Application has not specified scope. Find route within the locked scope.
       
  3087             rt = iInterfacer.FindRoute(dst, iOptions.iLockId, iOptions.iLockType, src_tmp, src_id);
       
  3088             if (rt != NULL)
       
  3089                 {
       
  3090                 aHead.iDstId = rt->iInterface.iScope[dstType];
       
  3091                 break;  // --> Success, route found
       
  3092                 }
       
  3093             // Special kludge, because the socket server locks unnecessarily to IAP level
       
  3094             // by default: if the locking is to IAP, then try finding an alternate route
       
  3095             // by the network id only.
       
  3096             if (iOptions.iLockType == EScopeType_IAP)
       
  3097                 {
       
  3098                 CIp6Interface *const ifp = iInterfacer.FindInterface(iOptions.iLockId, (TScopeType)iOptions.iLockType);
       
  3099                 if (ifp != NULL)
       
  3100                     {
       
  3101                     // At least one interface with matching IAP exists, try to find a route using the
       
  3102                     // network scope id from this interface.
       
  3103                     rt = iInterfacer.FindRoute(dst, ifp->iScope[EScopeType_NET], EScopeType_NET, src_tmp, src_id);
       
  3104                     if (rt != NULL)
       
  3105                         {
       
  3106                         aHead.iDstId = rt->iInterface.iScope[dstType];
       
  3107                         break;  // --> Success, route found
       
  3108                         }
       
  3109                     // should probing scope be also widened to network?
       
  3110                     }
       
  3111                 }
       
  3112             // For probing, limit it to locked scope, if any
       
  3113             dstType = iOptions.iLockType;
       
  3114             aHead.iDstId = iOptions.iLockId;
       
  3115             }
       
  3116         else
       
  3117             {
       
  3118             // If there is a locking to smaller scope than the requested destination scope,
       
  3119             // then try to find a route within the locked scope.
       
  3120             if (iOptions.iLockId && dstType > iOptions.iLockType)
       
  3121                 {
       
  3122                 rt = iInterfacer.FindRoute(dst, iOptions.iLockId, iOptions.iLockType, src_tmp, src_id);
       
  3123                 if (rt != NULL && rt->iInterface.iScope[dstType] == aHead.iDstId)
       
  3124                     break;  // --> Success, route found
       
  3125                 }
       
  3126             // If that route is not found or if the found interface does not match the required
       
  3127             // destination scope, then assume application wants to ignore the locking scope => search
       
  3128             // route by destination scope only.
       
  3129             rt = iInterfacer.FindRoute(dst, aHead.iDstId, dstType, src_tmp, src_id);
       
  3130             if (rt != NULL)
       
  3131                 break;  // --> Success, route found
       
  3132             }
       
  3133         //
       
  3134         // No route found, do the probing if enabled and return no route.
       
  3135         //
       
  3136         iInterfacer.ProbeDestination(dst, aHead.iDstId, dstType, src_tmp, src_id);
       
  3137         return iInfo.iNoInterfaceUp ? KErrInet6NoRoute : EFlow_PENDING; // --> Fail, route not found or pending
       
  3138         }
       
  3139     //
       
  3140     // The route (and interface) has been located
       
  3141     //
       
  3142     rt->Attach(*this);
       
  3143 
       
  3144     // Lock is applied only once (must be explicitly re-enabled, if new lock is to be applied)
       
  3145     iOptions.iLockId = 0;
       
  3146     const CIp6Interface &iface = rt->iInterface;
       
  3147 
       
  3148     aHead.iInterfaceIndex = iface.iScope[0];
       
  3149     //
       
  3150     TIp6Addr &src = aHead.ip6.SrcAddr();
       
  3151     // If source address is already specified, then skip the
       
  3152     // automatic address selection. TPacketHead::iSourceSet is
       
  3153     // initialized from the upper layer iLocalSet, and can be
       
  3154     // modified by the hooks in OpenL phase.
       
  3155     if (aHead.iSourceSet)
       
  3156         {
       
  3157         if (aHead.iSrcId == 0)
       
  3158             aHead.iSrcId = iface.iScope[(src.Scope()-1)&0xF];
       
  3159         return VerifyAddress(aHead, iface);
       
  3160         }
       
  3161     else if (iface.SelectSource(src, dst) == NULL)
       
  3162         {
       
  3163         const TIp6AddressInfo* address = iface.FindIpv4LinkLocalAddr();
       
  3164         
       
  3165         // If no appropriate routable address exists, fallback to any link local
       
  3166         // address regardless of prefix (this is required by the ZEROCONF RFC and
       
  3167         // a link local address can be used to reach any neighbour on-link using
       
  3168         // ARP).
       
  3169         if( address && address->IsAssigned() )
       
  3170             {
       
  3171             #ifdef _LOG
       
  3172                 TInetAddr addr;
       
  3173                 addr.SetAddress( address->iId );
       
  3174                 TBuf<39> addrStr;
       
  3175                 addr.Output( addrStr );
       
  3176                 
       
  3177                 Log::Printf(_L("CIp6Flow::RouteFlow - Unable to select source address for flow 0x%X based on destination - defaulting to link local address %S"), this, &addrStr);
       
  3178             #endif
       
  3179         
       
  3180             src = address->iId;
       
  3181             }
       
  3182         else
       
  3183             {
       
  3184             return EFlow_PENDING;
       
  3185             }
       
  3186         }
       
  3187     //
       
  3188     // Fix source address and scope
       
  3189     //
       
  3190     aHead.iSourceSet = 1;
       
  3191     aHead.iSrcId = iface.iScope[(src.Scope()-1)&0xF];
       
  3192     return EFlow_READY;
       
  3193     }
       
  3194 
       
  3195 
       
  3196 
       
  3197 //
       
  3198 // CIp6Flow::Connect
       
  3199 // *****************
       
  3200 void CIp6Flow::Connect()
       
  3201     /**
       
  3202     * Attach a flow to route and interface.
       
  3203     *
       
  3204     * At the start, iHead will contain the parameters affecting the
       
  3205     * flow connection (addresses, ports, etc.) in IPv6 variant of the
       
  3206     * iHead.
       
  3207     *
       
  3208     * Runs the "Open Phase" of flow hook mechanism for this flow. This
       
  3209     * will attach the interested outbound flow hooks to this flow. 
       
  3210     */
       
  3211     {
       
  3212 
       
  3213     // Run the open phase
       
  3214 retry_connect:
       
  3215     // Clean up all previous crud
       
  3216     iStatus = EFlow_READY;  // Make sure Disconnect doesn't call the caller back!
       
  3217     Disconnect();
       
  3218     iChanged = 0;
       
  3219     //
       
  3220     // Initialize the flow iHead (TPacketHead) from the upper layer information
       
  3221     //
       
  3222     const TInetAddr & localAddr = LocalAddr();
       
  3223     const TInetAddr & remoteAddr = RemoteAddr();
       
  3224     iHead.ip6.Init();                   // Set Version=6, hoplimit=0
       
  3225     iHead.ip6.SetVersion(0);            // We really don't know yet!
       
  3226     iHead.ip6.SetSrcAddr(localAddr.Ip6Address());
       
  3227     iHead.ip6.SetDstAddr(remoteAddr.Ip6Address());
       
  3228     // Load Selector Fields
       
  3229     iHead.iProtocol = (TUint8)Protocol();
       
  3230     iHead.iSrcPort = (TUint16)LocalPort();
       
  3231     iHead.iDstPort = (TUint16)RemotePort();
       
  3232     GetIcmpTypeCode(iHead.iIcmpType, iHead.iIcmpCode);
       
  3233     //
       
  3234     iHead.ip6.SetNextHeader(iHead.iProtocol);
       
  3235 
       
  3236     iHead.ip6.SetTrafficClass(iOptions.iTrafficClass);
       
  3237     iHead.ip6.SetFlowLabel(remoteAddr.FlowLabel());
       
  3238 
       
  3239     iHead.iSrcId = localAddr.Scope();
       
  3240     iHead.iSourceSet = iInfo.iLocalSet;
       
  3241     iHead.iDstId = remoteAddr.Scope();
       
  3242 
       
  3243     // Initialize locking (if any)
       
  3244     iOptions.iLockId = iInfo.iLockId;
       
  3245     iOptions.iLockType = iInfo.iLockType;
       
  3246 
       
  3247 #ifdef SYMBIAN_NETWORKING_UPS
       
  3248     TBool isScoped = EFalse;
       
  3249 #endif //SYMBIAN_NETWORKING_UPS
       
  3250 
       
  3251     for (;;) /* JUST FOR BREAK-EXITS, NOT REALLY A LOOP! */
       
  3252         {
       
  3253 #ifdef SYMBIAN_NETWORKING_UPS
       
  3254         // User Prompt Service (UPS) support.
       
  3255         //
       
  3256         // Generate NoBearer() upcalls on all flows that have an upper provider and have not
       
  3257         // yet had the scope set by ESOCK.  Generate NoBearer() even if enough information
       
  3258         // is available to route them with a straight Bearer() upcall.  This is to allow
       
  3259         // ESOCK to apply additional authorisation on any usage of a socket by a process.
       
  3260         //
       
  3261         // The check against upper provider is to exempt internal flows that aren't associated
       
  3262         // with an ESOCK socket - for example, those used for Neighbour Discovery or ICMP.
       
  3263         //
       
  3264 
       
  3265         TBool upsPromptingPossible = UPSPromptingPossible();      
       
  3266         if (upsPromptingPossible)
       
  3267             {
       
  3268             if ((iOptions.iLockId == 0 && (HasProvider() || iHead.iDstId == 0)) || iUpsAuthorisationRequired)
       
  3269                 {
       
  3270                 //
       
  3271                 // Accept only unambiguous loopback addresses if scope is not locked.
       
  3272                 //
       
  3273                                 
       
  3274                 //
       
  3275                 // iUpsAuthorisationRequired is True if iOptions.iLockId has been set by
       
  3276                 // SetOption KSoInterfaceIndex. This allows a gratituous (scoped) nobearer
       
  3277                 // up call to be made which results in a request being made to the Ups Server.
       
  3278                 //
       
  3279                 const TInt scope_level = iHead.ip6.DstAddr().Scope();
       
  3280 
       
  3281                 if (scope_level != KIp6AddrScopeNodeLocal)  // not a loopback address
       
  3282                     {
       
  3283                     // TODO 1116 NW: find out the correct means of preventing NoBearer() on 
       
  3284                     // destination addresses which are one of our interface addresses.
       
  3285                     // Pity this is going to take up cpu time for the check.
       
  3286                     //
       
  3287                     // iInterfacer.IsForMeAddress(iHead.ip6.DstAddr(), 0) seems inappropriate
       
  3288                     // as it doesn't do scope matching and works with interface index second argument,
       
  3289                     // which is meaningless in this context.
       
  3290                     // 
       
  3291                     // iInterfacer.FindInterface(RemoteAddr()) seems more appropriate, but not
       
  3292                     // entirely complete as it doesn't do ELoopback route matching.  So it will match
       
  3293                     // addresses.  If the address of an interface doesn't quite match, but it has a
       
  3294                     // route does match, then it won't pick tis up.  Perhaps it is good enough.  Perhaps
       
  3295                     // we don't need to do anything here at all!
       
  3296                     
       
  3297                     // Sending to a local interface address is treated as a loopback, so avoid issuing
       
  3298                     // NoBearer() in this case - drop through to Bearer().
       
  3299 
       
  3300                     // The following 2 lines have been removed as iInterfacer does not always return the correct interface
       
  3301                     // const CIp6Interface* ifp = iInterfacer.FindInterface(RemoteAddr());
       
  3302                     // if (ifp == NULL)
       
  3303                     
       
  3304                         {
       
  3305                         if (iHead.iDstId != 0 || scope_level == KIp6AddrScopeGlobal)
       
  3306                             {
       
  3307                             // If we *could* have gone through and attempted to connect the flow,
       
  3308                             // were it not for UPS, then mark this with a flag which will be
       
  3309                             // communicated to ESock in the NoBearer() upcall.  Effectively, we
       
  3310                             // are issuing what we think is a gratuitous NoBearer() just for ESock
       
  3311                             // to get a look in before the flow is connected.  ESock will
       
  3312                             // issue a SetOption(KSoConnectionInfo) with NetworkId KNetworkIdFromAddress
       
  3313                             // instead of what it thinks is the correct NetworkId (which is not going to
       
  3314                             // be based on the scope from the user).
       
  3315                             isScoped = ETrue;
       
  3316                             }
       
  3317                         break;
       
  3318                         }
       
  3319                     }
       
  3320                 } 
       
  3321             
       
  3322             // ESock can issue a SetOption(KSoConnectionInfo) with NetworkId KNetworkIdFromAddress after
       
  3323             // NoBearer() on flows where either the scope id has been set by the user, or the address is
       
  3324             // unambiguous.  This indicates that the flow is now able to be connected using the scope specified,
       
  3325             // rather than ESock giving the scope explicitly.  In effect, ESock is saying that it has "blessed"
       
  3326             // the flow for connection.  In other words, "attempt to attach the flow to a route, but determine
       
  3327             // the NetworkId from the socket address, as you've already indicated in the NoBearer() that you
       
  3328             // have enough information to do so".
       
  3329             //
       
  3330             // KNetworkIdFromAddress is just a magic way of signalling this method, as issuing a KSoConnectionInfo
       
  3331             // with NetworkId == 0 is filtered out at a higher level.  Reset iLockId to zero as we've received
       
  3332             // the signal that we need.
       
  3333             //
       
  3334             
       
  3335             if (iOptions.iLockId == KNetworkIdFromAddress)
       
  3336                 {
       
  3337                 iOptions.iLockId = 0;
       
  3338                 }
       
  3339             }
       
  3340         else
       
  3341             {
       
  3342             if (iHead.iDstId == 0 && iOptions.iLockId == 0)
       
  3343                 {
       
  3344                 //
       
  3345                 // Accept only unambiguous addresses if scope is not locked. -MikaL
       
  3346                 //
       
  3347                 const TInt scope_level = iHead.ip6.DstAddr().Scope();
       
  3348                 if (scope_level != KIp6AddrScopeGlobal &&   // not IPv6 global address
       
  3349                     scope_level != KIp6AddrScopeNodeLocal)  // not a loopback address
       
  3350                     break;
       
  3351                 }                           
       
  3352             }
       
  3353 #else
       
  3354         if (iHead.iDstId == 0 && iOptions.iLockId == 0)
       
  3355             {
       
  3356             //
       
  3357             // Accept only unambiguous addresses if scope is not locked. -MikaL
       
  3358             //
       
  3359             const TInt scope_level = iHead.ip6.DstAddr().Scope();
       
  3360             if (scope_level != KIp6AddrScopeGlobal &&   // not IPv6 global address
       
  3361                 scope_level != KIp6AddrScopeNodeLocal)  // not a loopback address
       
  3362                 break;
       
  3363             }
       
  3364 #endif
       
  3365 
       
  3366         iStatus = RouteFlow(iHead);
       
  3367         if (iStatus != 0)
       
  3368             break;
       
  3369         iHdrSize = 0;
       
  3370         iStatus = iMgr->FlowSetupHooks(*this);
       
  3371 
       
  3372         if (iStatus != 0)
       
  3373             break;          // Pending or fatal state, cannot proceed.
       
  3374 
       
  3375 #ifndef SYMBIAN_NETWORKING_UPS
       
  3376         // Decide on what destinations require network services capabily:
       
  3377         // - if it is my own assigned address allow without capability (IsMyPrefix test)
       
  3378         // - otherwise, allow only node local destinations (loopbacks)
       
  3379             if (!ApplyStaticSecurityCheck())
       
  3380                 {
       
  3381                 return;             
       
  3382                 }
       
  3383 #else
       
  3384         // Decide on what destinations require network services capabily:
       
  3385         // - if it is my own assigned address allow without capability (IsMyPrefix test)
       
  3386         // - otherwise, allow only node local destinations (loopbacks)
       
  3387         if (!upsPromptingPossible)
       
  3388             {
       
  3389             if (!ApplyStaticSecurityCheck())
       
  3390                 {
       
  3391                 return;             
       
  3392                 }
       
  3393             }
       
  3394                 
       
  3395 #endif
       
  3396         //
       
  3397         // The final interface has been located
       
  3398         //
       
  3399         Start();
       
  3400         SelectNextHop();
       
  3401         if (iStatus != 0)
       
  3402             return;
       
  3403         ASSERT(iRoute != NULL);
       
  3404 #ifdef _LOG
       
  3405             {
       
  3406             TLogAddressPrefix src(iInfo.iLocal);
       
  3407             TLogAddressPrefix dst(iInfo.iRemote);
       
  3408             Log::Printf(_L("\t\tFlow[%u] Connect: prot=%d src=[%S], dst=[%S] attached to IF %u [%S]"),
       
  3409                 this, (TInt)iInfo.iProtocol, &src, &dst, iRoute->iInterface.iScope[0], &iRoute->iInterface.iName);
       
  3410             }
       
  3411 #endif
       
  3412         TPckgBuf<TSoIfConnectionInfo> netinfo;
       
  3413         netinfo().iIAPId = iRoute->iInterface.iScope[EScopeType_IAP];
       
  3414         netinfo().iNetworkId = iRoute->iInterface.iScope[EScopeType_NET];
       
  3415         Bearer(netinfo);
       
  3416         RefreshFlow();
       
  3417         return;
       
  3418         }
       
  3419     //
       
  3420     // Cannot locate any interface for the flow.
       
  3421     // Punt the flow directly into holding state
       
  3422     //
       
  3423     iInterfacer.MoveToHolding(*this);
       
  3424     ASSERT(iRoute != NULL);
       
  3425 #ifdef _LOG
       
  3426         {
       
  3427         TLogAddressPrefix src(iInfo.iLocal);
       
  3428         TLogAddressPrefix dst(iInfo.iRemote);
       
  3429         Log::Printf(_L("\t\tFlow[%u] Connect: prot=%d src=[%S], dst=[%S] into holding (%d)"),
       
  3430             this, (TInt)iInfo.iProtocol, &src, &dst, iStatus);
       
  3431         }
       
  3432 #endif
       
  3433     if (iStatus > 0)
       
  3434         {
       
  3435         // The next hop could not be selected because no suitable
       
  3436         // interface or route matched the requirements. Need to
       
  3437         // activate new interfaces (or just keep waiting for them)
       
  3438 
       
  3439         if (iInfo.iNoInterfaceUp == 0)
       
  3440             {
       
  3441             // Because NoBearer may cause immediate call to SetOption with
       
  3442             // connection info, there are the following problems:
       
  3443             //
       
  3444             // 1) The connection info SetOption should wake up the flow, and
       
  3445             //    needs to call SetStatus(EFlow_READY). If flow is pending,
       
  3446             //    it will cause a CanSend. This must be prevented => Thus,
       
  3447             //    for NoBearer call, iStatus is temporarily set to READY.
       
  3448             // 2) Must detect whether NoBearer called SetOption, and if it
       
  3449             //    did, this code must retry the connect. => Thus, remember
       
  3450             //    current locking and see if it has changed during the
       
  3451             //    NoBearer.
       
  3452             // 
       
  3453             const TInt old_status = iStatus;
       
  3454             const TUint old_type = iInfo.iLockType;
       
  3455             const TUint32 old_id = iInfo.iLockId;
       
  3456             iStatus = EFlow_READY;
       
  3457 
       
  3458             _LIT8(KProtoIPv6, "protocol=ip6");
       
  3459             _LIT8(KProtoIPv4, "protocol=ip");
       
  3460 
       
  3461 #ifdef SYMBIAN_NETWORKING_UPS
       
  3462             const TInt KMaxArgLen = 19;     // sufficient for longest string length ("protocol=ip6 scoped")
       
  3463             TBuf8<KMaxArgLen> arg(iHead.ip6.DstAddr().IsV4Mapped() ? KProtoIPv4() : KProtoIPv6());
       
  3464             if (isScoped)
       
  3465                 {
       
  3466                 _LIT8(KScoped, " scoped");
       
  3467                 arg.Append(KScoped());
       
  3468                 }
       
  3469                     
       
  3470             if (iUpsAuthorisationRequired)
       
  3471                 {
       
  3472                 // A NoBearer upcall is being made after a set option KSoInterfaceIndex
       
  3473                 // which will result in a request to the UPS Server.
       
  3474                 // Set a flag to indicate that a UPS request is pending.
       
  3475                 // This flag will be reset when a KSoConnectionInfo is received in
       
  3476                 // response to the NoBearer upcall.
       
  3477                 iUpsAuthorisationPending = ETrue;                   
       
  3478                 }
       
  3479             NoBearer(arg);
       
  3480 #else
       
  3481             NoBearer(iHead.ip6.DstAddr().IsV4Mapped() ? KProtoIPv4() : KProtoIPv6());
       
  3482 #endif
       
  3483             if (iInfo.iLockType != old_type || iInfo.iLockId != old_id)
       
  3484                 goto retry_connect;
       
  3485             //
       
  3486             // NoBearer didn't call or change locking, restore
       
  3487             // original pending status and exit.
       
  3488             //
       
  3489             iStatus = old_status;
       
  3490             }
       
  3491         }
       
  3492     }
       
  3493 
       
  3494 #ifdef SYMBIAN_NETWORKING_UPS
       
  3495 TBool CIp6Flow::UPSPromptingPossible()
       
  3496     {
       
  3497     TBool upsPromptingPossible = EFalse;
       
  3498     
       
  3499     if (HasProvider())
       
  3500         {
       
  3501         TUint version = 0;
       
  3502         _LIT8(KProviderBindings, "MProviderBindings");
       
  3503         MProviderBindings* providerBindings = 0;
       
  3504         TRAPD(err, providerBindings  = (MProviderBindings*) GetProviderApiL(KProviderBindings, &version));              
       
  3505         if ((providerBindings != NULL) && (err == KErrNone ))
       
  3506             {
       
  3507             upsPromptingPossible = providerBindings->HasSocket();                               
       
  3508             }
       
  3509         }
       
  3510     return upsPromptingPossible;    
       
  3511     }
       
  3512 #endif
       
  3513 
       
  3514 TBool CIp6Flow::ApplyStaticSecurityCheck()
       
  3515     {
       
  3516     TBool rc = ETrue;
       
  3517     
       
  3518     ASSERT(iRoute);
       
  3519     if (!iRoute->IsMyPrefix() && iHead.ip6.DstAddr().Scope() > KIp6AddrScopeNodeLocal)
       
  3520         {
       
  3521         iStatus = CheckPolicy(KPolicyNetworkServices, "TCPIP Connect");
       
  3522         if (iStatus != 0)
       
  3523             rc = EFalse;                            
       
  3524         }
       
  3525     return rc;      
       
  3526     }
       
  3527 // CIp6Flow::Disconnect
       
  3528 // ********************
       
  3529 void CIp6Flow::Disconnect()
       
  3530     /**
       
  3531     * Disconnect flow (remove hooks).
       
  3532     */
       
  3533     {
       
  3534     iChanged = 1;
       
  3535     iHead.iPacket.Free();
       
  3536     RemoveHooks();
       
  3537     //
       
  3538     // Setting EFlow_READY should cause a wakeup for the
       
  3539     // SAP, if the flow status is pending.
       
  3540     // *WARNING* As Disconnect() is called in various
       
  3541     // contexts, there is a danger for infinite
       
  3542     // recursion, if this is called carelessly for
       
  3543     // PENDING flows...  -- msa
       
  3544     SetStatus(EFlow_READY);
       
  3545     }
       
  3546 
       
  3547 //
       
  3548 // CIp6Flow::InterfaceSMtu/InterfaceRMtu
       
  3549 // *************************************
       
  3550 // Return interface semd MTUs, if connected.
       
  3551 TInt CIp6Flow::InterfaceSMtu() const
       
  3552     {
       
  3553     return iRoute ? iRoute->iInterface.iSMtu : KErrNotReady;
       
  3554     }
       
  3555 
       
  3556 // Return interface receive MTUs, if connected.
       
  3557 TInt CIp6Flow::InterfaceRMtu() const
       
  3558     {
       
  3559     return iRoute ? iRoute->iInterface.iRMtu : KErrNotReady;
       
  3560     }
       
  3561 
       
  3562 //
       
  3563 // Local utility functions
       
  3564 //
       
  3565 static TInt GetIntValue(const TDesC8 &aOption, TInt aDefault)
       
  3566     {
       
  3567     if (aOption.Length() < (TInt)sizeof(TInt))
       
  3568         return aDefault;
       
  3569     // note: here it is assumed that the Ptr() is properly
       
  3570     // aligned, but for debug check it! -- msa)
       
  3571     ASSERT((((TUint)aOption.Ptr()) & 0x3) == 0);
       
  3572     return *((TInt *)aOption.Ptr());
       
  3573     }
       
  3574 
       
  3575 static void SetIntValue(TDes8 &aOption, TInt aValue)
       
  3576     {
       
  3577     aOption = TPtrC8((TUint8 *)&aValue, sizeof(aValue));
       
  3578     }
       
  3579 //
       
  3580 // CIp6Flow::GetOption
       
  3581 // *******************
       
  3582 TInt CIp6Flow::GetOption(TUint aLevel, TUint aName, TDes8 &aOption) const
       
  3583     {
       
  3584     if (aLevel == KSolInetIp)
       
  3585         {
       
  3586         switch(aName)
       
  3587             {
       
  3588         case KSoIpTOS:
       
  3589             SetIntValue(aOption, iOptions.iTrafficClass);
       
  3590             return KErrNone;
       
  3591         case KSoIpEcn:
       
  3592             SetIntValue(aOption, iOptions.iTrafficClass & 3);
       
  3593             return KErrNone;
       
  3594         case KSoIpTTL:              // Old IPv4 option
       
  3595         case KSoIp6UnicastHops:     // New IPv6/4 option
       
  3596             SetIntValue(aOption,
       
  3597                 // ...return explicitly set value, if defined by socket option
       
  3598                 iOptions.iHopLimit >= 0 ? iOptions.iHopLimit :
       
  3599                 // ...return current value from interface, if connected flow
       
  3600                 iRoute ? iRoute->iInterface.iHopLimit :
       
  3601                 // ...return system default otherwise
       
  3602                 iInterfacer.iMaxTTL);
       
  3603             return KErrNone;
       
  3604         case KSoIp6InterfaceUnicastHops:    // ignores any socket option which would override the current setting
       
  3605             SetIntValue(aOption,
       
  3606                 // ...return current value from interface, if connected flow
       
  3607                 iRoute ? iRoute->iInterface.iHopLimit :
       
  3608                 // ...return system default otherwise
       
  3609                 iInterfacer.iMaxTTL);
       
  3610             return KErrNone;
       
  3611         case KSoIp6MulticastHops:
       
  3612             // If no socket specific option has been set, then return the default 1.
       
  3613             SetIntValue(aOption, iOptions.iMulticastHops < 0 ? 1 : iOptions.iMulticastHops);
       
  3614             return KErrNone;
       
  3615         case KSoIp6MulticastLoop:
       
  3616             SetIntValue(aOption, iOptions.iMulticastLoop);
       
  3617             return KErrNone;
       
  3618         case KSoNoInterfaceError:
       
  3619             SetIntValue(aOption, iInfo.iNoInterfaceError);
       
  3620             return KErrNone;
       
  3621         case KSoInterfaceIndex:
       
  3622             SetIntValue(aOption, (TInt)(
       
  3623                 (iInfo.iLockType == 0) ? iInfo.iLockId :
       
  3624                 (iRoute && !iRoute->IsHoldingRoute()) ? iRoute->iInterface.iScope[0] :
       
  3625                 0));
       
  3626             return KErrNone;
       
  3627         case KSoKeepInterfaceUp:
       
  3628             SetIntValue(aOption, iOptions.iKeepInterfaceUp);
       
  3629             return KErrNone;
       
  3630         case KSoNextHop:
       
  3631             // Return information about the current route/next hop selection.
       
  3632             if (aOption.Length() != sizeof(TInetRouteInfo))
       
  3633                 return KErrArgument;
       
  3634             if (iStatus == EFlow_READY && iRoute)
       
  3635                 {
       
  3636                 TInetRouteInfo &opt = *(TInetRouteInfo*)aOption.Ptr();
       
  3637                 TTime stamp;
       
  3638                 stamp.UniversalTime();
       
  3639                 const CIp6Route *route = iRoute->iRouter ? iRoute->iRouter : iRoute;
       
  3640                 route->FillRouteInfo(opt, route->iInterface.Elapsed(stamp));
       
  3641                 return KErrNone;
       
  3642                 }
       
  3643             return KErrNotReady;    // The flow is not connected.
       
  3644         default:
       
  3645             break;
       
  3646             }
       
  3647         }
       
  3648     return iMgr->GetFlowOption(aLevel, aName, aOption, *this);
       
  3649     }
       
  3650 // CIp6Flow::SetOption
       
  3651 // *******************
       
  3652 TInt CIp6Flow::SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption)
       
  3653     {
       
  3654     if (aLevel == KSolInetIp)
       
  3655         {
       
  3656         // ...so far all implemented options use only int
       
  3657         // parameter. Just save code space and prefetch value,
       
  3658         // whether it is needed or not (GetIntValue should be safe
       
  3659         // to call in all cases).
       
  3660         const TInt val = GetIntValue(aOption, 0);
       
  3661         switch (aName)
       
  3662             {
       
  3663         // IPv4 TOS and IPv6 TrafficClass fields are now split to the TOS part and
       
  3664         // to the Explicit Congestion Notification (ECN) part (the least significant two
       
  3665         // bits). TCP SAP may prevent modifying the ECN bits with the TOS option. With UDP
       
  3666         // the option works in the traditional way.
       
  3667         case KSoIpTOS:
       
  3668             if (val < 0 || val > 255)
       
  3669                 return KErrArgument;    // Invalid option value
       
  3670 
       
  3671             if (val != iOptions.iTrafficClass)
       
  3672                 {
       
  3673                 iOptions.iTrafficClass = (TUint8)val;
       
  3674                 iChanged = 1;
       
  3675                 }
       
  3676             return KErrNone;
       
  3677         case KSoIpEcn:
       
  3678             if (val < 0 || val > 3)
       
  3679                 return KErrArgument;
       
  3680             if (val != (iOptions.iTrafficClass & 3))
       
  3681                 {
       
  3682                 TUint8 tosfield = (TUint8)val;
       
  3683                 tosfield |= iOptions.iTrafficClass & 0xfc;
       
  3684                 iOptions.iTrafficClass = tosfield;
       
  3685                 iChanged = 1;
       
  3686                 }
       
  3687             return KErrNone;
       
  3688         case KSoIpTTL:              // Old IPv4 option
       
  3689         case KSoIp6UnicastHops:     // New IPv6/4 option
       
  3690             if (val < -1 || val > 255)
       
  3691                 return KErrArgument;
       
  3692             if (val != iOptions.iHopLimit)
       
  3693                 {
       
  3694                 iOptions.iHopLimit = (TInt16)val;
       
  3695                 iChanged = 1;
       
  3696                 }
       
  3697             return KErrNone;
       
  3698         case KSoIp6MulticastHops:
       
  3699             if (val < -1 || val > 255)
       
  3700                 return KErrArgument;
       
  3701             if (val != iOptions.iMulticastHops)
       
  3702                 {
       
  3703                 iOptions.iMulticastHops = (TInt16)val;
       
  3704                 iChanged = 1;
       
  3705                 }
       
  3706             return KErrNone;
       
  3707         case KSoIp6MulticastLoop:
       
  3708             // For now, assume this option doesn't require iChanged processing!
       
  3709             if (val == 0)
       
  3710                 iOptions.iMulticastLoop = 0;    // disable loopback of multicast
       
  3711             else if (val == 1)
       
  3712                 iOptions.iMulticastLoop = 1;    // enable loopback of multicast
       
  3713             else
       
  3714                 return KErrArgument;
       
  3715             //break;
       
  3716             return KErrNone;  // was 'break'? why? fixed to return 9.1.2002/msa
       
  3717         case KSoNoInterfaceError:
       
  3718             // Control whether flow gets interface errors or not
       
  3719             if (val == 0)
       
  3720                 iInfo.iNoInterfaceError = 0;
       
  3721             else if (val == 1)
       
  3722                 iInfo.iNoInterfaceError = 1;
       
  3723             else
       
  3724                 return KErrArgument;
       
  3725             return KErrNone;
       
  3726         case KSoInterfaceIndex:
       
  3727             // Fix flow to a specific interface, if non-zero
       
  3728             if (iInfo.iLockType != 0 || iInfo.iLockId != (TUint)val)
       
  3729                 {
       
  3730                 iInfo.iLockType = EScopeType_IF;
       
  3731                 iInfo.iLockId = (TUint)val;
       
  3732                 iChanged = 1;
       
  3733 #ifdef SYMBIAN_NETWORKING_UPS
       
  3734                 //
       
  3735                 // iInfo.iLockId == 0 is tested as a condition which allows 
       
  3736                 // entry into the logical branch in CIp6Flow::Connect() that
       
  3737                 // triggers a NoBearer up call. A TNoBearer message results in
       
  3738                 // a call to the UPS Server. Setting iUpsAuthorisationRequired
       
  3739                 // ensures this branch is executed.
       
  3740                 // 
       
  3741                 iUpsAuthorisationRequired = ETrue;
       
  3742 #endif
       
  3743                 }
       
  3744             return KErrNone;
       
  3745         case KSoKeepInterfaceUp:
       
  3746             // Just treat any non-zero val as "1"
       
  3747             if ((int)iOptions.iKeepInterfaceUp == (val != 0))
       
  3748                 return KErrNone; // Value not changed
       
  3749             iOptions.iKeepInterfaceUp = (val != 0);
       
  3750             // Update the flow count on the interface
       
  3751             if (iRoute)
       
  3752                 iRoute->iInterface.UpdateFlowCount((val != 0) ? 1 : -1);
       
  3753             return KErrNone;
       
  3754         case KSoNoSourceAddressSelect:
       
  3755             iInfo.iLocalSet = 1;
       
  3756             return KErrNone;
       
  3757         case KSoNextHop:
       
  3758             // Force next hop selection. The option argument is ignored.
       
  3759             Start();
       
  3760             SelectNextHop();
       
  3761             return iStatus <= 0 ? iStatus : KErrNotReady;
       
  3762         default:
       
  3763             break;
       
  3764             }
       
  3765         }
       
  3766     else if (aLevel == STATIC_CAST(TUint, KSOLProvider))
       
  3767         {
       
  3768         const TUint optlen = aOption.Length();
       
  3769         const TUint8 *optptr = aOption.Ptr();
       
  3770 
       
  3771         if (aName == (TUint)KSoConnectionInfo)
       
  3772             {
       
  3773             if (optlen >= sizeof(TSoIfConnectionInfo))
       
  3774                 {
       
  3775                 const TSoIfConnectionInfo &opt = *(TSoIfConnectionInfo*)optptr;
       
  3776                 TUint new_type;
       
  3777                 TUint new_lock;
       
  3778                 if (opt.iIAPId)
       
  3779                     {
       
  3780                     // Locking on IAP
       
  3781                     new_type = EScopeType_IAP;
       
  3782                     new_lock = opt.iIAPId;
       
  3783                     }
       
  3784                 else
       
  3785                     {
       
  3786                     // Locking on NetworkId
       
  3787                     new_type = EScopeType_NET;
       
  3788                     new_lock = opt.iNetworkId;
       
  3789                     }
       
  3790                 if (iInfo.iLockId != 0 && iInfo.iLockType == EScopeType_IF)
       
  3791                     {
       
  3792                     // If the flow has already been explicitly locked to an interface
       
  3793                     // using the socket option KSoInterfaceIndex, then assume application
       
  3794                     // really wants to override the default connection settings that would
       
  3795                     // be coming from the socket server.
       
  3796                     LOG(Log::Printf(_L("\t\tFlow[%u] Set ConnectionInfo: IF=%d already interface locked, %S=%d ignored"),
       
  3797                         this, (TInt)iInfo.iLockId, &LogScopeName(new_type), (TInt)new_lock));
       
  3798 
       
  3799 #ifdef SYMBIAN_NETWORKING_UPS
       
  3800                 if (iUpsAuthorisationRequired && iUpsAuthorisationPending)
       
  3801                     {
       
  3802                     // This branch is called as a direct result of a NoBearer call which has
       
  3803                     // resulted from CIp6Flow::Connect() being called after SetOption(KSoInterfaceIndex).
       
  3804                     // Now reset the flags which allowed a NoBearer upcall to be made.
       
  3805 
       
  3806                     iUpsAuthorisationRequired = EFalse;
       
  3807                     iUpsAuthorisationPending  = EFalse;
       
  3808 
       
  3809                     // The following three lines cater for the following stack trace:
       
  3810                     //  CIp6Flow::Connect()
       
  3811                     //      NoBearer("scoped")
       
  3812                     //          SetOption(KSoConnectionInfo(KNetworkIdFromAddress))
       
  3813                     // When we eventually return to CIp6Flow::Connect(), we need to ensure that it
       
  3814                     // retries the flow connect.
       
  3815                     if (new_type == EScopeType_NET && new_lock == KNetworkIdFromAddress)
       
  3816                         {
       
  3817                         iInfo.iLockType = new_type;
       
  3818                         iInfo.iLockId = new_lock;
       
  3819                         }
       
  3820 
       
  3821                     SetStatus(EFlow_READY);                 
       
  3822                     }
       
  3823 #endif
       
  3824 
       
  3825                     return KErrNone;
       
  3826                     }
       
  3827                 LOG(Log::Printf(_L("\t\tFlow[%u] Set ConnectionInfo: %S=%d -> %S=%d"),
       
  3828                     this, &LogScopeName(iInfo.iLockType), (TInt)iInfo.iLockId, &LogScopeName(new_type), (TInt)new_lock));
       
  3829                 if (iInfo.iLockType != new_type || iInfo.iLockId != new_lock)
       
  3830                     {
       
  3831                     iInfo.iLockType = new_type;
       
  3832                     iInfo.iLockId = new_lock;
       
  3833                     iChanged = 1;
       
  3834                     // Wake up the flow, if pending
       
  3835                     SetStatus(EFlow_READY);
       
  3836                     }
       
  3837                 return KErrNone;
       
  3838                 }
       
  3839             LOG(Log::Printf(_L("\t\tFlow[%u] Set ConnectionInfo: Bad TSoIfConnection"), this));
       
  3840             return KErrArgument;
       
  3841             }
       
  3842         }
       
  3843     return iMgr->SetFlowOption(aLevel, aName, aOption, *this);
       
  3844     }
       
  3845 
       
  3846 //
       
  3847 // ************************
       
  3848 // CIp6Route Implementation
       
  3849 // ************************
       
  3850 //
       
  3851 //
       
  3852 // CIp6Route
       
  3853 // *********
       
  3854 // Construct & Destruct
       
  3855 //
       
  3856 CIp6Route::CIp6Route(TUint aIndex, CIp6Manager &aMgr, const TIp6Addr &aAddr, TInt aPrefix, CIp6Interface &aInterface)
       
  3857 :   iIndex(aIndex),
       
  3858     iInterfacer(aMgr),
       
  3859     iPrefix(aAddr),
       
  3860     iLength((TUint8)aPrefix),
       
  3861     iMetric(KPreferenceMetric[ERoutePreference_MEDIUM]),
       
  3862     iTimeout(CIp6RouteTimeoutLinkage::Timeout),
       
  3863     iInterface(aInterface)
       
  3864     {
       
  3865     }
       
  3866 
       
  3867 CIp6Route::~CIp6Route()
       
  3868     {
       
  3869     LOG(Log::Write(_L("~CIp6Route()")));
       
  3870     CancelTimer();  // ..if any pending
       
  3871     iPacket.Free();     // (if any)
       
  3872     //
       
  3873     // Just detach all flows attached to this route
       
  3874     // (Should have a "route down" error status? -- msa)
       
  3875     //
       
  3876     TInt changed = 0;
       
  3877     CIp6Flow *f;
       
  3878     while ((f = iFlowList) != NULL)
       
  3879         {
       
  3880         iFlowList = f->iNext;
       
  3881         f->iRoute = NULL;
       
  3882         f->iNext = NULL;
       
  3883         f->SetStatus(EFlow_DOWN);
       
  3884         changed -= f->iOptions.iKeepInterfaceUp;
       
  3885         }
       
  3886     iInterface.UpdateFlowCount(changed);
       
  3887     }
       
  3888 
       
  3889 //
       
  3890 // CIp6Route::Attach
       
  3891 // *****************
       
  3892 /**
       
  3893 // Attach flow to a specific route (it has already
       
  3894 // been decided elsewhere that this route is the
       
  3895 // correct one; this function is just pure housekeeping)
       
  3896 */
       
  3897 void CIp6Route::Attach(CIp6Flow &aFlow)
       
  3898     {
       
  3899     //
       
  3900     // A flow can only be attached to one route at time.
       
  3901     // If different from this, then detach first.
       
  3902     //
       
  3903     if (aFlow.iRoute != this)
       
  3904         {
       
  3905         if (aFlow.iRoute)
       
  3906             aFlow.iRoute->Detach(aFlow);
       
  3907         //
       
  3908         // Add to the flow list of the route
       
  3909         //
       
  3910         aFlow.iRoute = this;
       
  3911         aFlow.iNext = iFlowList;
       
  3912         iFlowList = &aFlow;
       
  3913         iInterface.UpdateFlowCount(aFlow.iOptions.iKeepInterfaceUp);
       
  3914         }
       
  3915     }
       
  3916 
       
  3917 #ifdef _LOG
       
  3918 const TDesC &CIp6Route::LogRouteType() const
       
  3919     {
       
  3920     _LIT(KIncomplete,   "Incomplete");
       
  3921     _LIT(KReachable,    "Reachable");
       
  3922     _LIT(KStale,        "Stale");
       
  3923     _LIT(KDelay,        "Delay");
       
  3924     _LIT(KProbe,        "Probe");
       
  3925 
       
  3926     _LIT(KMyPrefix,     "MyPrefix");
       
  3927     _LIT(KOnlink,       "Onlink");
       
  3928     _LIT(KGateway,      "Gateway");
       
  3929     _LIT(KAnycast,      "Anycast");
       
  3930     _LIT(KRedirect,     "Redirect");
       
  3931     _LIT(KMulticast,    "Multicast");
       
  3932     _LIT(KHolding,      "Holding");
       
  3933     _LIT(KInvalid,      "Invalid");
       
  3934 
       
  3935     switch (iState)
       
  3936         {
       
  3937         case EIncomplete: return KIncomplete;
       
  3938         case ELoopback: if (iIsMulticast) return KMulticast; else return KMyPrefix;
       
  3939         case EOnlink: return KOnlink;
       
  3940         case EGateway: return KGateway;
       
  3941         case ERedirect: return KRedirect;
       
  3942         case EAnycast: return KAnycast;
       
  3943         case EReachable: return KReachable;
       
  3944         case EStale: return KStale;
       
  3945         case EDelay: return KDelay;
       
  3946         case EProbe: return KProbe;
       
  3947         case EHolding: return KHolding;
       
  3948         default: break;
       
  3949         }
       
  3950     return KInvalid;
       
  3951     }
       
  3952 
       
  3953 void CIp6Route::LogRoute(const TLifetime aLifetime) const
       
  3954     {
       
  3955     // index interface route/prefix type address ...
       
  3956     _LIT(KFormat0, "\tIF %u [%S] ROUTE %u %S %S %S metric=%d");
       
  3957     _LIT(KFormat1, "\tIF %u [%S] ROUTE %u %S %S %S metric=%d LT=%u");
       
  3958     _LIT(KFormat2, "\tIF %u [%S] ROUTE %u %S %S %S metric=%d REMOVED");
       
  3959 
       
  3960     const TDesC &format =
       
  3961         aLifetime == KLifetimeForever ? KFormat0() : aLifetime != 0 ? KFormat1() : KFormat2();
       
  3962 
       
  3963     TLogAddressPrefix tmp(iPrefix, iLength);
       
  3964     TLogAddressPrefix gw;
       
  3965     if (Type() != CIp6Route::ELoopback)
       
  3966         {
       
  3967         TInetAddr addr;
       
  3968         iAddress.GetAddress(addr);
       
  3969         gw.Set(addr);
       
  3970         }
       
  3971     Log::Printf(format,
       
  3972         iInterface.iScope[0],
       
  3973         &iInterface.iName,
       
  3974         iIndex,
       
  3975         &tmp,
       
  3976         &LogRouteType(),
       
  3977         &gw,
       
  3978         (TInt)iMetric,
       
  3979         aLifetime);
       
  3980     }
       
  3981 #endif
       
  3982 //
       
  3983 // CIp6Route::Attach
       
  3984 // *****************
       
  3985 /**
       
  3986 // Detach all flows from one route and add them to this route
       
  3987 //
       
  3988 // @li *NOTE*
       
  3989 //  As flows are set into PENDING state, this makes only
       
  3990 //  sense as a method of the "holding route".
       
  3991 */
       
  3992 void CIp6Route::Attach(CIp6Route &aRoute)
       
  3993     {
       
  3994     CIp6Flow *f;
       
  3995     TInt count = 0;
       
  3996 
       
  3997     while ((f = aRoute.iFlowList) != NULL)
       
  3998         {
       
  3999         aRoute.iFlowList = f->iNext;
       
  4000         f->iNext = iFlowList;
       
  4001         iFlowList = f;
       
  4002         f->iRoute = this;
       
  4003         // reminder: SetStatus for pending (> 0) will not change the
       
  4004         // flow status, if it already is in error state (the error
       
  4005         // state is preserved) -- msa
       
  4006         f->SetStatus(EFlow_PENDING);
       
  4007         //++count;
       
  4008         count += f->iOptions.iKeepInterfaceUp;
       
  4009         }
       
  4010     iInterface.UpdateFlowCount(count);
       
  4011     aRoute.iInterface.UpdateFlowCount(-count);
       
  4012     }
       
  4013 
       
  4014 //
       
  4015 // CIp6Route::Detach
       
  4016 // *****************
       
  4017 // Disconnect flow from route. Just pure house keeping
       
  4018 void CIp6Route::Detach(CIp6Flow &aFlow)
       
  4019     {
       
  4020     if (this == aFlow.iRoute)
       
  4021         {
       
  4022         CIp6Flow **h, *f;
       
  4023         //
       
  4024         // Some concern: Will this list normally be short enough for
       
  4025         // this simple scan or should a double linked list with
       
  4026         // deque applied?  -- msa
       
  4027         //
       
  4028         aFlow.iRoute = NULL;
       
  4029         for (h = &iFlowList; (f = *h) != NULL; h = &(f->iNext))
       
  4030             if (f == &aFlow)
       
  4031                 {
       
  4032                 *h = f->iNext;
       
  4033                 iInterface.UpdateFlowCount(-(int)aFlow.iOptions.iKeepInterfaceUp);
       
  4034                 return;                 // Succesful/Normal result.
       
  4035                 }
       
  4036         User::Panic(_L("DEBUG"), 0);    // Should never happen!
       
  4037         }
       
  4038     else
       
  4039         {
       
  4040         ASSERT(aFlow.iRoute == NULL);
       
  4041         }
       
  4042     }
       
  4043 
       
  4044 //
       
  4045 // CIp6Route::NofifyFlows
       
  4046 // **********************
       
  4047 // Notify all flows attached to this route
       
  4048 void CIp6Route::NotifyFlows(TInt aState)
       
  4049     {
       
  4050     TFlowNotifyList list;
       
  4051     for (CIp6Flow *f = iFlowList; f; f = f->iNext)
       
  4052         f->Notify(list, aState);
       
  4053     list.Deliver(aState);
       
  4054     }
       
  4055 
       
  4056 // CIp6Route::SetChanged
       
  4057 // *********************
       
  4058 // Set iChanged for all flows on this route
       
  4059 TInt CIp6Route::SetChanged(const TInt aScope) const
       
  4060     {
       
  4061     if (aScope > 0)
       
  4062         return iInterface.SetChanged(aScope-1);
       
  4063     TInt count = 0;
       
  4064     for (CIp6Flow *f = iFlowList; f; f = f->iNext)
       
  4065         count += f->SetChanged(0);
       
  4066     return count;
       
  4067     }
       
  4068 
       
  4069 //
       
  4070 //  CIp6Route::Send
       
  4071 //  ***************
       
  4072 /**
       
  4073 //  Send a packet to the attached interface,
       
  4074 //  @param aPacket  The packet to send (with info block).
       
  4075 //  @param aSrc     The source (just passed through, not significant)
       
  4076 //  @param aMulticastLoop
       
  4077 //      If non-zero and destination is multicast, then
       
  4078 //      pass copy of the packet to receivers on this node.
       
  4079 //  @return
       
  4080 //  @li < 0, no interface of some other missing component
       
  4081 //  @li = 0, packet sent, but interface does not want more after this
       
  4082 //  @li = 1, packet sent, and interface is willing to accept more
       
  4083 //
       
  4084 //  The packet "ownership" is always transfered, regardless of the return type,
       
  4085 //  aPacket should be empty after this.
       
  4086 //
       
  4087 //  On entry, the packet must have a info structure of RMBufSendInfo.
       
  4088 */
       
  4089 TInt CIp6Route::Send(RMBufChain& aPacket, CProtocolBase* aSrc, TInt aMulticastLoop)
       
  4090     {
       
  4091     TInt ret = KErrNotReady;
       
  4092     for (;;)            // Just to provide multiple exits (break) below
       
  4093         {
       
  4094         RMBufSendInfo *const info = RMBufSendPacket::PeekInfoInChain(aPacket);
       
  4095         if (!info)
       
  4096             break;
       
  4097 
       
  4098         // "Dereference" automatically when sent to a gateway route
       
  4099         if (iRouter)
       
  4100             {
       
  4101             if (info->iFlags & KIpDontRoute)
       
  4102                 break;  // "routing disabled", just drop the packet!
       
  4103             return iRouter->Send(aPacket, aSrc, aMulticastLoop);
       
  4104             }
       
  4105 
       
  4106         if (Type() == ELoopback)    // Use Type() to cover all loopback routes (like Anycast)
       
  4107             {
       
  4108             // Tag the packet as "loopback", so that inbound processing can easily
       
  4109             // recognize such packets (used in capability checks).
       
  4110             info->iFlags |= KIpLoopbackPacket;
       
  4111             // Set and clear KIpBroadcastOnLink depending on if destination is multicast.
       
  4112             // (this catches net broadcast and joined multicast groups).
       
  4113             if (iIsMulticast)
       
  4114                 info->iFlags |= KIpBroadcastOnLink;
       
  4115             else
       
  4116                 info->iFlags &= ~KIpBroadcastOnLink;
       
  4117     
       
  4118             // Do not require iNifIf on ELoopBack destinations
       
  4119             const TIp6Addr &dst = TInetAddr::Cast(info->iDstAddr).Ip6Address();
       
  4120             //
       
  4121             // Assume if route is multicast, then dest is also!
       
  4122             //
       
  4123             // *NOTE*
       
  4124             //  This branch only gets multicast routes for joined multicast
       
  4125             //  groups (Type() == ELoopback). Beware: there are also other
       
  4126             //  types of routes with multicast address prefix!
       
  4127             //
       
  4128             if (!iIsMulticast || dst.Scope() < KIp6AddrScopeLinkLocal)
       
  4129                 {
       
  4130                 // Destination is not multicast or has less than link local scope.
       
  4131                 // This is plain loopback in the stack internally.
       
  4132                 // No other special handling required.
       
  4133                 iInterface.iNifUser->iNetwork->Process(aPacket, (CProtocolBase *)iInterface.iNifIf);
       
  4134                 ret = 1;        // Return 1 to indicate "more packets can be sent"
       
  4135                 break;
       
  4136                 }
       
  4137             // Destination is multicast and has wider than node local scope...
       
  4138             if (aMulticastLoop)
       
  4139                 {
       
  4140                 // The packet must be both looped back and also sent out to interface,
       
  4141                 // a copy of the packet is needed...
       
  4142                 RMBufPacketBase clone;
       
  4143                 TRAP(ret, clone.CopyPackedL(aPacket));
       
  4144                 if (ret != KErrNone)
       
  4145                     {
       
  4146                     clone.Free();   // just in case...
       
  4147                     break;
       
  4148                     }
       
  4149                 iInterface.iNifUser->iNetwork->Process(clone, (CProtocolBase *)iInterface.iNifIf);
       
  4150                 ret = KErrNotReady; // (restoring the "default" return status)
       
  4151                 }
       
  4152             // Continue processing the multicast packet as any other packet, sending it
       
  4153             // to the interface..
       
  4154             }
       
  4155         else
       
  4156             {
       
  4157             if (iState == EIncomplete)
       
  4158                 {
       
  4159                 // The neighbor discovery is still in progress, need to queue
       
  4160                 // at least ONE packet to wait for it's completion. Swap the
       
  4161                 // content of the queue (iPacket) and current packet (aPacket)
       
  4162                 //
       
  4163                 // Also notify HOLD to hint flows that they shouldn't send anything
       
  4164                 // before the ND completion...
       
  4165                 //
       
  4166                 NotifyFlows(EFlow_HOLD); 
       
  4167                 RMBufChain tmp(iPacket);
       
  4168                 iPacket = aPacket;
       
  4169                 aPacket = tmp;
       
  4170                 ret = 1;
       
  4171                 break;
       
  4172                 }
       
  4173             else if (iInterface.NeedsND() &&
       
  4174                 (iState == EStale ||
       
  4175                  (iState == EReachable &&
       
  4176                 // iReachableTime needs to be represented in TickCount units -- msa
       
  4177                 (User::TickCount() - iTimeStamp) > iInterface.iReachableTime)))
       
  4178                 {
       
  4179                 // Start the delay timer
       
  4180                 iState = EDelay;
       
  4181                 iRetry = 1;
       
  4182                 // This a bit dangerous call, as iRoute->Timeout() also includes code to
       
  4183                 // do route destruction! Should be damn sure that this call doesn't
       
  4184                 // trigger that!!! -- msa
       
  4185                 Timeout();
       
  4186                 }
       
  4187             if (iAddress.Family())
       
  4188                 {
       
  4189                 // Copy address information into info destination address
       
  4190                 iAddress.GetAddress(info->iDstAddr);
       
  4191                 }
       
  4192             // Clear KIpBroadcastOnLink. It will be set in the Send of CIp6Interface
       
  4193             // if destination is IPv4 or IPv6 multicast address.
       
  4194             info->iFlags &= ~KIpBroadcastOnLink;
       
  4195             }
       
  4196         // If destination is still IP address and IPv4 mapped, then
       
  4197         // pass it to the interface as plain IPv4 address (KAfInet)!
       
  4198         // (even, if ND interface, this is still relevant for multicast
       
  4199         // destinations)
       
  4200         if ((TInetAddr::Cast(info->iDstAddr).IsV4Mapped()))
       
  4201             (TInetAddr::Cast(info->iDstAddr)).ConvertToV4();
       
  4202 
       
  4203         return iInterface.Send(aPacket, aSrc);
       
  4204         }
       
  4205     aPacket.Free(); // NOOP, if packet ownership taken by someone.
       
  4206     return ret;
       
  4207     }
       
  4208 
       
  4209 //
       
  4210 // CIp6Route::StartND
       
  4211 // ******************
       
  4212 // Start ND process.
       
  4213 // @param aSrc The source to be used.
       
  4214 void CIp6Route::StartND(const TIp6Addr &aSrc)
       
  4215     {
       
  4216     // There should be no need to test for EIncomplete. However, as some
       
  4217     // ND messages are also used in Point-to-Point links (RA), it is
       
  4218     // possible that EIncomplete routes get created for non-ND interfaces.
       
  4219     // Thus, NeedsND() is checked, and if not set, the route is directly
       
  4220     // changed into EReachable state,
       
  4221     ASSERT(iState == EIncomplete);
       
  4222 
       
  4223     if (!iInterface.NeedsND())
       
  4224         {
       
  4225         iState = EReachable;
       
  4226         return;
       
  4227         }
       
  4228     //
       
  4229     // On EIncomple route the timer is always active, if
       
  4230     // ND is in progress. When ND terminates, fail or success,
       
  4231     // the route state will not be EIncomplete!
       
  4232     //
       
  4233     if (!IsTimerActive())
       
  4234         {
       
  4235         // ...when incomplete, triggering SRC address
       
  4236         // is stored in the iAddress field of the route.
       
  4237         iAddress.SetAddress(aSrc);  // ..thus, store the src
       
  4238         iRetry = iInterface.iND.iMaxMulticastSolicit;
       
  4239         Timeout();
       
  4240         }
       
  4241     }
       
  4242 
       
  4243 //
       
  4244 // CIp6Route::Update
       
  4245 // *****************
       
  4246 /**
       
  4247 // Update route entry.
       
  4248 // @param   aFlags  How to update
       
  4249 // @param   The gateway (gateway routes) or link layer address (host routes).
       
  4250 // @param   The lifetime.
       
  4251 // @returns
       
  4252 //  @li 0, if state change cannot release any flows
       
  4253 //  @li 1, if state change potentially released flows
       
  4254 */
       
  4255 TInt CIp6Route::Update(TInt aFlags, const TSockAddr *aAddress, const TLifetime *const aLifetime)
       
  4256     {
       
  4257 //  const TUint family = aAddress ? aAddress->Family() : KAFUnspec;
       
  4258     const TSockAddr *const address = (aAddress && aAddress->Family() != KAFUnspec) ? aAddress : NULL;
       
  4259     TInt notify = 0;
       
  4260     switch (iState)
       
  4261         {
       
  4262         case ERedirect:
       
  4263         case EGateway:
       
  4264             if (address)
       
  4265                 {
       
  4266                 iAddress.SetAddress(*address);
       
  4267 
       
  4268                 // Changed address of a gateway entry (includes
       
  4269                 // case of when gateway entry is created). Must
       
  4270                 // now "refresh" the iRouter entry!
       
  4271                 // Should verify that Family is KAfInet6? -- msa
       
  4272                 CIp6Route *router = iInterface.FindNeighbor(iAddress.Ip6Address());
       
  4273                 if (router && router->iIsRouter)
       
  4274                     iRouter = router;
       
  4275                 else
       
  4276                     {
       
  4277                     // If route was ERedirect, it should never get here (and if it
       
  4278                     // gets, it should be deleted--however, "Update" cannot delete
       
  4279                     // the self (this). [should be ok, ERedirect is only installed from
       
  4280                     // ND handler, and it should make sure to install the host
       
  4281                     // route (ISROUTER=1) before creating the redirection! --msa]
       
  4282                     ASSERT(iState != ERedirect);
       
  4283                     iRouter = NULL;
       
  4284                     }
       
  4285                 notify = 1;
       
  4286                 }
       
  4287             // *FALL THROUGH*
       
  4288         case ELoopback:
       
  4289         case EOnlink:
       
  4290         default:
       
  4291             if (aLifetime)
       
  4292                 {
       
  4293                 //
       
  4294                 // Reset the lifetime of this route (aLifetime should be > 0, but
       
  4295                 // just as a safety measure, treat 0 as 1)
       
  4296                 CancelTimer();
       
  4297                 ASSERT(iRetry == 0);
       
  4298                 iRetry = 0;     // should be unnecessary..
       
  4299                 ASSERT(*aLifetime > 0);
       
  4300                 if (*aLifetime < KLifetimeForever)
       
  4301                     // NEED FIXING/LOOKING INTO: There is theoretical possibility that
       
  4302                     // timeout expires directly and deletes the route now... Should
       
  4303                     // prevent that somehow!  -- msa
       
  4304                     SetTimer(*aLifetime ? *aLifetime : 1);
       
  4305                 }
       
  4306             return notify;
       
  4307         //
       
  4308         // NEIGHBOR DISCOVERY SECTION
       
  4309         // --------------------------
       
  4310         case EIncomplete:
       
  4311             // TimeStamp can be set on every update, because the reachability
       
  4312             // algorithm kicks in only when entry is changhed into some other
       
  4313             // state. Setting it here guarantees that every IsHostRoute() has
       
  4314             // some reasonable value for the time stamp (all such routes are
       
  4315             // *ALWAYS* created as first into "EIncomplete" state). TimeStamp
       
  4316             // can then be used in the cleanup process to detect old unused
       
  4317             // entries (see CIp6Interface::Timeout()). [in other states,
       
  4318             // updating time stamp depends on the situation and cannot be done
       
  4319             // unconditionally -- msa]
       
  4320             iTimeStamp = User::TickCount();
       
  4321 #if 0
       
  4322             if (address == NULL)
       
  4323                 {
       
  4324                 // This is dubious, might cause a fail of some ND
       
  4325                 // conformance test. However, this is needed, because PPP
       
  4326                 // link needs to get it's IS ROUTER bit set, even if it
       
  4327                 // has no link layer addresses..
       
  4328                 // [if link layer address is missing, should ND enabled
       
  4329                 // interface just return here, and NOT do the ISROUTER
       
  4330                 // stuff? -- msa]
       
  4331                 if (iInterface.iHwAddr.Family() == KAFUnspec)
       
  4332                     {
       
  4333                     // If interface does not use link layer addresses,
       
  4334                     // just implicitly change into reachable state...
       
  4335                     iState = EReachable;
       
  4336                     }
       
  4337                 break;
       
  4338                 }
       
  4339             CancelTimer();          // if any active!
       
  4340             iAddress.SetAddress(*address);
       
  4341 #else
       
  4342             if (address == NULL)
       
  4343                 {
       
  4344                 // No address available (no target linklayer address)
       
  4345                 if ((aFlags & KRouteAdd_UPDATEONLY) != 0 &&
       
  4346                     // UPDATEONLY is set for NA, but not for REDIRECT related
       
  4347                     // target routes (which have ISROUTER set!). Redirect routes
       
  4348                     // must process the "router bit", even if no link address
       
  4349                     // is present. NA must drop the packet and NOT process
       
  4350                     // "router bit".
       
  4351                     iInterface.iHwAddr.Family() != KAFUnspec)
       
  4352                     // The link layer requires addresses. If the NA didn't have the
       
  4353                     // link layer address, drop the packet (RFC 2461, 7.2.5).
       
  4354                     return notify;
       
  4355                 // ..otherwise, proceed normally to update ISROUTER/ISHOST
       
  4356                 // (but DO LEAVE THE STATE AS INCOMPLETE!!!)
       
  4357                 break;
       
  4358                 }
       
  4359             else
       
  4360                 iAddress.SetAddress(*address);
       
  4361             CancelTimer();          // if any active!
       
  4362 #endif
       
  4363             iState = (aFlags & KRouteAdd_SOLICITED) ? EReachable : EStale;
       
  4364             if (iIsProbing)
       
  4365                 {
       
  4366                 iIsProbing = 0;
       
  4367                 Interfacer().iScanHolding = 1;
       
  4368                 }
       
  4369             notify = 1;
       
  4370             //
       
  4371             // Send queued packets (only one for now), if any
       
  4372             //
       
  4373             if (!iPacket.IsEmpty())
       
  4374                 {
       
  4375                 // Send should not reque this packet, but just in case,
       
  4376                 // use a tmp instead of calling Send(iPacket).
       
  4377                 RMBufChain tmp;
       
  4378                 tmp.Assign(iPacket);
       
  4379                 Send(tmp);
       
  4380                 tmp.Free(); // In case it failed.
       
  4381                 }
       
  4382             break;  // ..to the IS ROUTER processing
       
  4383         case EReachable:
       
  4384         case EStale:
       
  4385         case EDelay:
       
  4386         case EProbe:
       
  4387             // At this point, the state is one of the following and nothing else
       
  4388             //  EReachable (no timer)
       
  4389             //  EStale (no timer)
       
  4390             //  EDelay (timer active)
       
  4391             //  EProbe (timer active)
       
  4392             //
       
  4393             if (address && !iAddress.Match(*address))
       
  4394                 {
       
  4395                 if (aFlags & KRouteAdd_OVERRIDE)
       
  4396                     {
       
  4397                     iAddress.SetAddress(*address);
       
  4398                     iState = EStale;
       
  4399                     CancelTimer();  // Could have been in Probe or Delay!
       
  4400                     }
       
  4401                 else
       
  4402                     {
       
  4403                     // RFC 2461 7.2.5 does not require SOLICITED to be set for setting
       
  4404                     // STALE, but in APPENDIX C it looks like it should be required?
       
  4405                     //
       
  4406                     if (iState == EReachable /* && (aFlags & KRouteAdd_SOLICITED)*/)
       
  4407                         {
       
  4408                         iState = EStale;
       
  4409                         // no need to cancel timer, EReachable doesn't have one!
       
  4410                         LOG(LogRoute(KLifetimeForever));
       
  4411                         }
       
  4412                     return 0;
       
  4413                     }
       
  4414                 }
       
  4415             if (aFlags & KRouteAdd_SOLICITED)
       
  4416                 {
       
  4417                 iState = EReachable;
       
  4418                 CancelTimer();      // Could have been in Probe or Delay!
       
  4419                 iTimeStamp = User::TickCount();
       
  4420                 LOG(if (!notify) LogRoute(KLifetimeForever));
       
  4421                 }
       
  4422             break;
       
  4423         }
       
  4424     //
       
  4425     // Maintain IS ROUTER status (iIsRouter + iRoute pointers)
       
  4426     //
       
  4427     // Cannot have both ISROUTER and ISHOST set!
       
  4428     ASSERT((aFlags & (KRouteAdd_ISHOST|KRouteAdd_ISROUTER)) != (KRouteAdd_ISHOST|KRouteAdd_ISROUTER));
       
  4429     ASSERT(Type() == KRouteAdd_NEIGHBOR);   // Only Host Routes should get here
       
  4430     if (iIsRouter && (aFlags & KRouteAdd_ISHOST) != 0)
       
  4431         {
       
  4432         // IS-ROUTER changed from TRUE to FALSE
       
  4433         iIsRouter = 0;
       
  4434         iInterface.RouterChanged(this);
       
  4435         }
       
  4436     else if (!iIsRouter && (aFlags & KRouteAdd_ISROUTER) != 0)
       
  4437         {
       
  4438         // IS-ROUTER changed from FALSE to TRUE
       
  4439         iIsRouter = 1;
       
  4440         iInterface.RouterChanged(this);
       
  4441         notify = 1;
       
  4442         }
       
  4443     return notify;
       
  4444     }
       
  4445 
       
  4446 // CIp6Route::Timeout
       
  4447 // ******************
       
  4448 // A timeout expired for this route.
       
  4449 
       
  4450 //
       
  4451 // *WARNING*
       
  4452 //  This method is used both for starting the timers and also
       
  4453 //  as the timeout handler. When called to start the timer, iRetry
       
  4454 //  should always be non-zero, and this method MUST NEVER destroy
       
  4455 //  the route instance in such case...!!
       
  4456 //
       
  4457 //      On real timeout, aExpired == 1
       
  4458 //      On start timeout, aExpired == 0
       
  4459 //
       
  4460 // *NOTE*
       
  4461 //  In current version SetTimeout(0) will never call directly
       
  4462 //  expire (Timeout). Thus, it is also safe to use that
       
  4463 //  within this method, if necessary. (one does not need to
       
  4464 //  worry about intance being deleted away in middle of this
       
  4465 //  method).
       
  4466 //
       
  4467 void CIp6Route::Timeout(const TInt aExpired)
       
  4468     {
       
  4469     //
       
  4470     // What was I doing?
       
  4471     //
       
  4472     switch (iState)
       
  4473         {
       
  4474         case EIncomplete:
       
  4475             if (iRetry == 0)
       
  4476                 break;
       
  4477             //
       
  4478             // RFC-2461 7.2.2 says "...If the source address of the packet prompting the
       
  4479             // solicitation is the same as one of the addresses assigned to the outgoing
       
  4480             // interface, that address SHOULD be placed in the IP Source Address of the
       
  4481             // outgoing solicitation."
       
  4482             //
       
  4483             // Assume this src address is stored in iAddress at this point. Must be
       
  4484             // my own address (not verified here).
       
  4485                 {
       
  4486 #ifdef _LOG
       
  4487                 TLogAddressPrefix tmpsrc(iAddress.Ip6Address());
       
  4488                 TLogAddressPrefix tmpdst(iPrefix);
       
  4489                 Log::Printf(_L("\tIF %u [%S] ROUTE %u Send NS from [%S] for target [%S]"), iInterface.iScope[0], &iInterface.iName, iIndex, &tmpsrc, &tmpdst);
       
  4490 #endif
       
  4491                 iRetry -= 1;
       
  4492                 // unspecified address as dst will use solicited node based on target
       
  4493                 iInterface.SendNeighbors(KInet6ICMP_NeighborSol, NULL, iPrefix, &iAddress.Ip6Address());
       
  4494                 if (iIsProbing && iRetry == 0)
       
  4495                     {
       
  4496                     // When probing, set the last timeout specially. This will prevent
       
  4497                     // reactivating the probing and rate limits it.
       
  4498                     SetTimer(iInterface.iND.iRateLimitProbingTime);
       
  4499                     }
       
  4500                 else
       
  4501                     Interfacer().SetTimerWithUnits(iTimeout, iInterface.iRetransTimer);
       
  4502                 }
       
  4503             return;
       
  4504         case EDelay:
       
  4505             if (iRetry)
       
  4506                 {
       
  4507                 // A request to start the delay
       
  4508                 iRetry = 0;
       
  4509                 SetTimer(iInterface.iND.iDelayFirstProbeTime);
       
  4510                 return;
       
  4511                 }
       
  4512             // The requested delay has completed...
       
  4513             iRetry = iInterface.iND.iMaxUnicastSolicit;
       
  4514             iState = EProbe;
       
  4515             LOG(LogRoute(KLifetimeForever));
       
  4516             /* FALL THFROUGH */
       
  4517         case EProbe:
       
  4518                 {
       
  4519                 if (iRetry == 0)
       
  4520                     {
       
  4521                     break;
       
  4522                     }
       
  4523                 else if (iRetry == 1)
       
  4524                     {
       
  4525                     // try broadcast first otherwise it will break the route
       
  4526                     iInterface.SendNeighbors(KInet6ICMP_NeighborSol, NULL, iPrefix);
       
  4527                     Interfacer().SetTimerWithUnits(iTimeout, iInterface.iRetransTimer);
       
  4528                     return;
       
  4529                     }
       
  4530                 else
       
  4531                     {
       
  4532                     iRetry -= 1;
       
  4533                     iInterface.SendNeighbors(KInet6ICMP_NeighborSol, this, iPrefix);
       
  4534                     Interfacer().SetTimerWithUnits(iTimeout, iInterface.iRetransTimer);
       
  4535                     return;
       
  4536                     }
       
  4537                 }
       
  4538 
       
  4539         case ELoopback:
       
  4540             // *Note* It is assumed for now, that iPreferred == 0
       
  4541             // for all ELoopback routes that represent joined multicast
       
  4542             // groups (=> timer expiration will delete group). Some
       
  4543             // other logic may be designed later -- msa
       
  4544 #ifdef _LOG
       
  4545             {
       
  4546                 TLogAddressPrefix tmp(iPrefix, iLength);
       
  4547                 Log::Printf(_L("\tIF %u [%S] ROUTE %u Timeout prefix [%S]"), iInterface.iScope[0], &iInterface.iName, iIndex, &tmp);
       
  4548             }
       
  4549 #endif
       
  4550             if (iLifetime.iPreferred > 0)
       
  4551                 {
       
  4552                 // Prefix is changing from preferred to deprecated
       
  4553                 // (pick the value into temporary and zero iPreferred
       
  4554                 // before setting the timeout, just in case timeout
       
  4555                 // expires immediate -- ít shouldn't because of delay
       
  4556                 // is > 0, but as it costs nothing to be safe.. -- msa
       
  4557                 const TLifetime value = iLifetime.iPreferred;
       
  4558                 iLifetime.iPreferred = 0;
       
  4559                 iLifetime.iDeprecated = 1;
       
  4560                 SetTimer(value);
       
  4561                 LOG(LogRoute(value));
       
  4562                 return;
       
  4563                 }
       
  4564             //
       
  4565             // Prefix lifetime has expired
       
  4566             //
       
  4567             iInterface.iSequence++;
       
  4568             break;
       
  4569         case EOnlink:
       
  4570         case EGateway:
       
  4571         case EReachable:
       
  4572         case EStale:
       
  4573         default:
       
  4574             //
       
  4575             // The default processing with iRetry==0 is to delete the route
       
  4576             //
       
  4577             if (iRetry == 0)
       
  4578                 break;
       
  4579             iRetry = 0;
       
  4580             return;
       
  4581 
       
  4582         case EHolding:
       
  4583             //
       
  4584             // Holding route timeout handling is different from others:
       
  4585             // It should poll the held flows and "expire" too old ones!
       
  4586             //
       
  4587             const TUint max_time = Interfacer().iMaxHoldingTime;
       
  4588             //
       
  4589             // if iMaxHoldingTime == 0, no "expire" happens
       
  4590             //
       
  4591             if (max_time > 0)
       
  4592                 {
       
  4593                 const TUint tick_now = User::TickCount();
       
  4594 
       
  4595                 TUint tick_limit; // max_time converted into ticks (conversion code block below)
       
  4596                     {
       
  4597                     TReal interval;
       
  4598                     (void)Math::Round(interval, (max_time * 1000000.0) / TickPeriod(), 0);
       
  4599                     (void)Math::Int((TInt32 &)tick_limit, interval);
       
  4600                     }
       
  4601                 LOG(Log::Printf(_L("HoldingRoute: max=%d [s], tick_limit = %d, tick_now = %d"), max_time, tick_limit, tick_now));
       
  4602 
       
  4603                 TUint longest_hold = 0;
       
  4604                 TUint flows_left = 0; // just 0 = no flows, 1= flows left holding
       
  4605                 TFlowNotifyList list;
       
  4606                 for (CIp6Flow *f = iFlowList; f != NULL; f = f->iNext)
       
  4607                     {
       
  4608                     const TUint hold_time = tick_now - f->iTimeStamp;
       
  4609                     if (hold_time >= tick_limit)
       
  4610                         list.Insert(*f);
       
  4611                     else
       
  4612                         {
       
  4613                         // Flow still has time to wait left. Keep
       
  4614                         // track of the longest unexpired hold (for
       
  4615                         // setting the next timer...)
       
  4616                         //
       
  4617                         flows_left = 1;
       
  4618                         if (hold_time > longest_hold)
       
  4619                             longest_hold = hold_time;
       
  4620                         }
       
  4621                     }
       
  4622                 list.Deliver(KErrInet6NoRoute);
       
  4623                 //
       
  4624                 // (Re)Enable polling timer, if flows still attached
       
  4625                 // [note: longest_hold can be 0, if we just added the first flow]
       
  4626                 if (flows_left)
       
  4627                     {
       
  4628                     // ... it might be better to precompute integer approximation of ticks per second
       
  4629                     // to be used where exact timing is not so essential (instead of this floating
       
  4630                     // arithmetic). then it would be just integer divisition with truncate:
       
  4631                     //     max_time = (tick_limit - longest_hold + ticks_per_second + 1) / ticks_per_second;
       
  4632                     // and
       
  4633                     //     tick_limit = ticks_per_second * max_time;
       
  4634                     // -- msa
       
  4635                     //
       
  4636                     TReal interval;
       
  4637                     (void)Math::Round(interval, 1.0 * (tick_limit - longest_hold) * TickPeriod() / 1000000.0, 0);
       
  4638                     (void)Math::Int((TInt32 &)max_time, interval);
       
  4639                     LOG(Log::Printf(_L("HoldingRoute: next after %d ticks [= %d+1s]"), tick_limit-longest_hold, max_time));
       
  4640                     SetTimer(max_time + 1); // add +1 to guarantee > 0, and that surely enough time has passed
       
  4641                     }
       
  4642                 }
       
  4643             return;
       
  4644         }
       
  4645     //
       
  4646     // Gets here only if this route should be removed (if possible)
       
  4647     // (iRetry == 0)
       
  4648     //
       
  4649     // If there is any packet waiting for transmission, then report
       
  4650     // ICMP host/address unreachable for it (currently iPacket is
       
  4651     // only used for neighbor cache routes). If iPacket is used
       
  4652     // in some other route types, a test for the route type could
       
  4653     // be inserted here...
       
  4654     Interfacer().IcmpSend(iPacket, TIcmpTypeCode(KInet4ICMP_Unreachable, 1, KInet6ICMP_Unreachable, 3));
       
  4655 
       
  4656     if (aExpired)
       
  4657         iInterface.RemoveRoute(this);   // "this" is DELETED! Beware!
       
  4658     else
       
  4659         // Be tricky, and destruct with a delay...
       
  4660         SetTimer(1);
       
  4661     }
       
  4662 
       
  4663 //
       
  4664 // ****************************
       
  4665 // CIp6Interface Implementation
       
  4666 // ****************************
       
  4667 //
       
  4668 
       
  4669 CIp6Interface::CIp6Interface(CIp6Manager &aMgr, TUint aIndex, const TDesC &aName) :
       
  4670     iInterfacer(aMgr), iName(aName), iTimeout(CIp6InterfaceTimeoutLinkage::Timeout)
       
  4671     {
       
  4672     __DECLARE_NAME(_S("CIp6Interface"));
       
  4673     iScope[0] = aIndex;
       
  4674     LOG(Log::Printf(_L("\tIF %u [%S] New"), iScope[0], &iName));
       
  4675     }
       
  4676 
       
  4677 // CIp6Interface::Index, Name and Scope
       
  4678 // ************************************
       
  4679 // The basic information about the interface
       
  4680 //
       
  4681 TUint32 CIp6Interface::Index() const
       
  4682     {
       
  4683     return iScope[0];
       
  4684     }
       
  4685 
       
  4686 const TDesC & CIp6Interface::Name() const
       
  4687     {
       
  4688     return iName;
       
  4689     }
       
  4690 
       
  4691 TUint32 CIp6Interface::Scope(const TScopeType aType) const
       
  4692     {
       
  4693     return ((TUint)aType > EScopeType_NET) ? 0 : iScope[aType];
       
  4694     }
       
  4695 
       
  4696 //
       
  4697 // CIp6Interface::UpdateFlowCount
       
  4698 // ******************************
       
  4699 //
       
  4700 void CIp6Interface::UpdateFlowCount(TInt aChange)
       
  4701     {
       
  4702     if (aChange == 0)
       
  4703         return;             // No change!
       
  4704     iFlows += aChange;
       
  4705     LOG(Log::Printf(_L("\tIF %u [%S] Attached flows changed from %d to %d"), iScope[0], &iName, iFlows - aChange, iFlows));
       
  4706     ASSERT(iFlows >= 0);
       
  4707 
       
  4708     if (!iNifIf || !iNifIf->Notify())
       
  4709         return;             // No interface attached or Nifman
       
  4710                             // doesn't care--nothing more to do.
       
  4711     if (iFlows == 0)
       
  4712         {
       
  4713         //
       
  4714         // The flow count for this interface has gone to Zero
       
  4715         // Notify the NIFMAN that the interface can be closed,
       
  4716         // if it wants to do so
       
  4717         //
       
  4718         LOG(Log::Printf(_L("\tIF %u [%S] CloseRoute"), iScope[0], &iName));
       
  4719         iNifIf->Notify()->CloseRoute();
       
  4720         }
       
  4721     else if (iFlows == aChange)
       
  4722         {
       
  4723         //
       
  4724         // The flow just changed from 0 to something non-zero
       
  4725         // Notify NIFMAN that interface is back in use.
       
  4726         LOG(Log::Printf(_L("\tIF %u [%S] OpenRoute"), iScope[0], &iName, aChange));
       
  4727         iNifIf->Notify()->OpenRoute();
       
  4728         }
       
  4729     }
       
  4730 
       
  4731 // CIp6Interface::Send
       
  4732 // *******************
       
  4733 // Send a packet to the interface
       
  4734 TInt CIp6Interface::Send(RMBufChain& aPacket, CProtocolBase* aSrc)
       
  4735     {
       
  4736     TInt ret = KErrNotReady;
       
  4737 
       
  4738     for (;iNifIf;)  // ** NOT REAL LOOP, ONLY FOR CONVENIENT ERROR EXITS! **
       
  4739         {
       
  4740         if (iState == EFlow_HOLD)
       
  4741             {
       
  4742             iHoldQueue.Append(aPacket);
       
  4743             LOG(Log::Printf(_L("\tIF %u [%S] Send holding packets"), iScope[0], &iName));
       
  4744 
       
  4745             return 0;       // Try to request "no more packets"
       
  4746             }
       
  4747         // Because Send will consume the packet, must pick up the parameters
       
  4748         // for the packet activity notification before it!
       
  4749         RMBufSendInfo *const info = RMBufSendPacket::PeekInfoInChain(aPacket);
       
  4750         if (info == NULL)
       
  4751             break;  // ...should really never happen, but just in case!
       
  4752         const TUint bytes = (TUint)info->iLength;
       
  4753         const TBool reset_timer = (info->iFlags & KIpKeepInterfaceUp) != 0;
       
  4754         
       
  4755         // If destination at this point is still IPv4 or IPv6 multicast address
       
  4756         // set the KIpBroadcastOnLink flag. Note, that the flag is not cleared
       
  4757         // becuase this bit may have been correctly set earlier for broadcast
       
  4758         // addresses (which are not recognized as multicast here!).
       
  4759         if (TInetAddr::Cast(info->iDstAddr).IsMulticast())
       
  4760             info->iFlags |= KIpBroadcastOnLink;
       
  4761         LOG(PktLog(_L("\tIF %u [%S] SEND prot=%d src=%S dst=%S len=%d"), *info, iScope[0], iName));
       
  4762         ret = iNifIf->Send(aPacket, aSrc);
       
  4763         if (ret <= 0)
       
  4764             {
       
  4765             // The Send returns are "officially" only
       
  4766             //  1 = Packet Accepted ok
       
  4767             //  0 = Packet Accepted, don't send more before StartSending
       
  4768             // However, some may return < 0 to signal an error (and not
       
  4769             // follow it up with start sending). So, the following logic
       
  4770             // is implemented:
       
  4771             //  Returned 1, no change in interface state or flow [does not enter this branch of code]
       
  4772             //  Returned 0, interface and flows are set to HOLD
       
  4773             //  Returned < 0, no change in interface state, error is
       
  4774             //  reported to the flows!
       
  4775             LOG(Log::Printf(_L("\tIF %u [%S] NIF Send returned HOLD (%d)"), iScope[0], &iName, ret));
       
  4776             TInt state = ret;
       
  4777             if (state == 0)
       
  4778                 iState = state = EFlow_HOLD;    // Convert "0" to HOLD state
       
  4779             NotifyFlows(state);
       
  4780             }
       
  4781         if (iNifIf->Notify())
       
  4782             (void)iNifIf->Notify()->PacketActivity(EOutgoing, bytes, reset_timer);
       
  4783 
       
  4784         // If the packet ownership is not taken at this point, someone is not
       
  4785         // working as specified (Process() or Send()).
       
  4786         ASSERT(aPacket.IsEmpty());
       
  4787         break;  // ** MUST TERMINATE THE "FAKE FOR"-LOOP ALWAYS!
       
  4788         }
       
  4789     aPacket.Free(); // If nobody took it, release it!
       
  4790     return ret;
       
  4791     }
       
  4792 
       
  4793 //
       
  4794 // CIp6Interface::UpdateMulticast
       
  4795 // ******************************
       
  4796 /**
       
  4797 //  Maintain multicast membership status at low level (add/remove the
       
  4798 //  route and update the interface; must not do MLD!)
       
  4799 //
       
  4800 // @param   aMulticast speficies the multicast group to join or leave
       
  4801 // @param   aLifetime, = 0 => leave group, != 0, join group. (the life time
       
  4802 // of multicast group is controlled by join/leaves, and the actual non-zero
       
  4803 // value is not used for anything else except as a flag).
       
  4804 //
       
  4805 // @returns
       
  4806 // @li  KErrNone, if join or leave succeeds,
       
  4807 // @li  KErrNotFound, if leave for non-existent group
       
  4808 // @li  KErrNoMemory, if group cannot be joined due to memory allocation failures
       
  4809 // @li  any other error, if NIF rejects the join .
       
  4810 */
       
  4811 TInt CIp6Interface::UpdateMulticast(const TIp6Addr &aMulticast, const TLifetime aLifetime)
       
  4812     {
       
  4813     //
       
  4814     // Construct Join/leave option buffer
       
  4815     //
       
  4816     TPckgBuf<TIp6Mreq> opt;
       
  4817     opt().iAddr = aMulticast;
       
  4818     opt().iInterface = iScope[0];
       
  4819     //
       
  4820     // NIF needs to be notified only if it exists, and if the scope
       
  4821     // is larger than node-local. NIF can use this notify
       
  4822     // to maintain multicast filters for the interface,
       
  4823     // if it supports such feature.
       
  4824     const TBool notify_nif = (iNifIf != NULL) && (aMulticast.Scope() > KIp6AddrScopeNodeLocal);
       
  4825     //
       
  4826     // Get the multicast route entry representing the group
       
  4827     //
       
  4828     CIp6Route *route = GetRoute(aMulticast, 128, KRouteAdd_MYPREFIX|KRouteAdd_UPDATEONLY);
       
  4829     if (route == NULL)
       
  4830         {
       
  4831         //
       
  4832         // The multicast group does not exist yet.
       
  4833         //
       
  4834         if (aLifetime == 0)
       
  4835             return KErrNotFound;    // not joined to this group, cannot leave.
       
  4836 
       
  4837         if (notify_nif)
       
  4838             {
       
  4839             const TInt err = iNifIf->Control(KSolInetIp, KSoIp6JoinGroup, opt);
       
  4840             if (err < 0 && err != KErrNotSupported)
       
  4841                 return err;             // Interface explicitly rejects the join.
       
  4842             }
       
  4843         route = GetRoute(aMulticast, 128, KRouteAdd_MYPREFIX);
       
  4844         if (route == NULL)
       
  4845             return KErrNoMemory;
       
  4846         // note: above GetRoute just created a special multicast "myprefix"
       
  4847         // route entry. This is exactly same as joining to the multicast
       
  4848         // group. Could consider generating the NotifyMulticastEvent from
       
  4849         // the "address route creation event", and not sending the route
       
  4850         // event in such case at all (implementation of joined multicast
       
  4851         // groups as "multicast my-address" entries is internal implementation
       
  4852         // issue). -- msa
       
  4853         NotifyMulticastEvent(EventTypeAdd, aMulticast, aLifetime);
       
  4854         return KErrNone;
       
  4855         }
       
  4856 
       
  4857     // Join or Leave to an existing group. The iLifetime.iCount
       
  4858     // counts the *ADDITIONAL* users after the first one. With one
       
  4859     // user, the iCount == 0!
       
  4860 
       
  4861     ASSERT(route->iIsMulticast);
       
  4862 
       
  4863     if (aLifetime)
       
  4864         {
       
  4865         //
       
  4866         // Additional join to an existing multicast group
       
  4867         //
       
  4868         route->iLifetime.iCount++;
       
  4869         }
       
  4870     else if (route->iLifetime.iCount == 0)
       
  4871         {
       
  4872         //
       
  4873         // Last user left the group
       
  4874         //
       
  4875         NotifyMulticastEvent(EventTypeDelete, aMulticast, aLifetime);
       
  4876         // note: generates remove of "multicast myprefix" entry, above
       
  4877         // multicast notify could be generated from that.. -- msa
       
  4878         RemoveRoute(route);
       
  4879         if (notify_nif)
       
  4880             (void)iNifIf->Control(KSolInetIp, KSoIp6LeaveGroup, opt);
       
  4881         }
       
  4882     else
       
  4883         {
       
  4884         //
       
  4885         // Non-last user left the group
       
  4886         //
       
  4887         route->iLifetime.iCount--;
       
  4888         }
       
  4889     return KErrNone;
       
  4890     }
       
  4891 
       
  4892 // CIp6Interface::DoBind
       
  4893 // *********************
       
  4894 /**
       
  4895 // Finalizes the connection between the network and interface, assuming
       
  4896 // the CNifIfBase instance is connected to the interface
       
  4897 //
       
  4898 // @note
       
  4899 //      Actually combined "close/rebind/open" method, which closes any
       
  4900 //      existing bindings, and sets the new binding (if provided).
       
  4901 //      There should probably be separate Open/Close methods.
       
  4902 */
       
  4903 TInt CIp6Interface::DoBind(CIp6NifUser *aNifUser, CNifIfBase *aIf)
       
  4904     {
       
  4905     ASSERT(aNifUser != NULL);
       
  4906 
       
  4907     iNifUser = aNifUser;    // Do this always!
       
  4908 
       
  4909     if (iNifIf == aIf)
       
  4910         return KErrNone;    // Do nothing, already bound to this (or both NULL)!
       
  4911 
       
  4912     Reset();                // ...back to initial state!
       
  4913     if (aIf)
       
  4914         {
       
  4915         //
       
  4916         // A new NIF interface to bind
       
  4917         //
       
  4918         aIf->Open();
       
  4919         iNifIf = aIf;
       
  4920 
       
  4921         if (aNifUser->iNetwork)
       
  4922             {
       
  4923             TRAPD(err, aIf->BindL(aNifUser->iNetwork->Protocol()));
       
  4924             if (err != KErrNone)
       
  4925                 {
       
  4926                 //
       
  4927                 // Bind failure
       
  4928                 //
       
  4929                 iNifIf = NULL;
       
  4930                 aIf->Close();
       
  4931                 }
       
  4932             else
       
  4933                 {
       
  4934                 // ...notify network layer, in case any hook is interested...
       
  4935                 // [The above BindL may have caused StartSending and other
       
  4936                 // large actions to happen, so just to be safe, need to
       
  4937                 // check that iNetwork is still attached... -- msa]
       
  4938                 if (iNifUser->iNetwork)
       
  4939                     iNifUser->iNetwork->InterfaceAttached(iName, iNifIf);
       
  4940 /*              if (iFlows > 0 && aIf->Notify())
       
  4941                 aIf->Notify()->OpenRoute();*/
       
  4942                 }
       
  4943             return err;
       
  4944             }
       
  4945         else
       
  4946             {
       
  4947             // Interface instance exists, but there is no network to
       
  4948             // connect. What to do? Should be left into pending state
       
  4949             // until the network registers and then call the BindL?
       
  4950             // -- msa
       
  4951             User::Panic(_L("DEBUG"), 0);
       
  4952             }
       
  4953         }
       
  4954     return KErrNotReady;
       
  4955     }
       
  4956 
       
  4957 
       
  4958 //
       
  4959 // MakeFullAddress
       
  4960 // ***************
       
  4961 static void MakeFullAddress(TIp6Addr &aPrefix, TUint aLength, const TUint8 *aId, TInt aIdLen)
       
  4962     /**
       
  4963     * Combine hardware id and prefix into single address.
       
  4964     *
       
  4965     * If ID is longer than available room in address, the extra bits
       
  4966     * from the start of the ID are ignored.
       
  4967     *
       
  4968     * If ID is shorter than available room in address, the unspecified
       
  4969     * bits in the ID part will be ZERO.
       
  4970     *
       
  4971     * @retval aPrefix The prefix part of the address, and final address on return.
       
  4972     * @param aLength The prefix length in BITS.
       
  4973     * @param aId The Id value
       
  4974     * @param aIdLen The id length in full bytes.
       
  4975     */
       
  4976     {
       
  4977     TInetAddr msk;
       
  4978     msk.PrefixMask(aLength);
       
  4979 
       
  4980     // Initialize properly aligned ID
       
  4981     // (copy id to the end of TIp6Addr and zero remaining)
       
  4982     TIp6Addr id;
       
  4983     TInt i = sizeof(id.u.iAddr8);
       
  4984     do
       
  4985         {
       
  4986         id.u.iAddr8[--i] = --aIdLen >= 0 ? aId[aIdLen] : (TUint8) 0;
       
  4987         }while(i > 0);
       
  4988     // Added explicit cast (TUint8) above to suppress WINS compiler warning
       
  4989 
       
  4990     // Merge id with prefix
       
  4991     const TIp6Addr &m = msk.Ip6Address();
       
  4992 
       
  4993 /*    for (TInt j = 4; --j >= 0;)
       
  4994         aPrefix.u.iAddr32[j] = (aPrefix.u.iAddr32[j] & m.u.iAddr32[j]) | (id.u.iAddr32[j] & (~m.u.iAddr32[j]));
       
  4995 */  
       
  4996     // We don't loop. Just do the calculation.
       
  4997     aPrefix.u.iAddr32[3] = (aPrefix.u.iAddr32[3] & m.u.iAddr32[3]) | (id.u.iAddr32[3] & (~m.u.iAddr32[3]));
       
  4998     aPrefix.u.iAddr32[2] = (aPrefix.u.iAddr32[2] & m.u.iAddr32[2]) | (id.u.iAddr32[2] & (~m.u.iAddr32[2]));
       
  4999     aPrefix.u.iAddr32[1] = (aPrefix.u.iAddr32[1] & m.u.iAddr32[1]) | (id.u.iAddr32[1] & (~m.u.iAddr32[1]));
       
  5000     aPrefix.u.iAddr32[0] = (aPrefix.u.iAddr32[0] & m.u.iAddr32[0]) | (id.u.iAddr32[0] & (~m.u.iAddr32[0]));
       
  5001     }
       
  5002 
       
  5003 
       
  5004 //
       
  5005 // CIp6Interface::Elapsed
       
  5006 // **********************
       
  5007 TLifetime CIp6Interface::Elapsed(const TTime &aStamp) const
       
  5008     {
       
  5009     TTimeIntervalSeconds elapsed;
       
  5010     aStamp.SecondsFrom(iTimeStamp, elapsed);
       
  5011     TInt elapsedInt = elapsed.Int();
       
  5012     // Return 0, if time is earlier than time stamp (clock turned back?)
       
  5013     return (TLifetime) (elapsedInt < 0 ? 0 : elapsedInt);
       
  5014     }
       
  5015 
       
  5016 //
       
  5017 // CIp6Interface::SetPrefix()
       
  5018 // **************************
       
  5019 //
       
  5020 // *NOTE* to delete a prefix, aLifeTime == 0 (and set aForce non-ZERO, if 2h safeguard
       
  5021 // is to be disabled)
       
  5022 //
       
  5023 void CIp6Interface::SetPrefix(const TIp6Addr &aPrefix, const TUint aLength, const TInt aForce, const TLifetime aLifetime, const TLifetime aPreferred)
       
  5024     {
       
  5025     ASSERT(aLength <= 128);
       
  5026 #ifdef SYMBIAN_TCPIPDHCP_UPDATE      
       
  5027     #ifdef _DEBUG
       
  5028         LOG(Log::Printf(_L("<>\tCIp6Interface::SetPrefix() lifetime = (%d)"),aLifetime));
       
  5029     #endif
       
  5030 #endif // SYMBIAN_TCPIPDHCP_UPDATE          
       
  5031     if (TIp46Addr::Cast(aPrefix).IsMulticast() ||
       
  5032         // ...basicly, all prefixes on the interface should have the same
       
  5033         // length (128 - idlength). However, make an exception for special
       
  5034         // interfaces with with idlength = 0 (like 6to4). [Note: idlength
       
  5035         // is not directly stored, but computed as (128-iAddress.iPrefix)]
       
  5036         (iAddress.iPrefix != 128 && iAddress.iPrefix != aLength && aLength != 128))
       
  5037         return;     // silently ignore all attemps to put in funny prefixes!
       
  5038 
       
  5039     CIp6Route *prefix = GetRoute(aPrefix, aLength,
       
  5040         // Set UPDATEONLY, if lifetime is ZERO (don't create!)
       
  5041         KRouteAdd_MYPREFIX | (aLifetime > 0 ? 0 : KRouteAdd_UPDATEONLY)
       
  5042         );
       
  5043     if (prefix == NULL)
       
  5044         return;     // OOPS, out of memory or something...
       
  5045 
       
  5046     // Lifetime is maintained relative to the iTimeStamp of the interface
       
  5047     TTime stamp;
       
  5048     stamp.UniversalTime();
       
  5049     const TLifetime current_time = Elapsed(stamp);
       
  5050     // Compute old remaining lifetime (StoredLifetime in RFC 2462/5.5.3)
       
  5051 
       
  5052     TLifetime storedLifetime = (prefix->iLifetime.iStored > current_time) ?
       
  5053         prefix->iLifetime.iStored - current_time : 0 /* 0 = expired*/;
       
  5054 
       
  5055     // The logic we are counting on here: if storedLifetime above has something set,
       
  5056     // this must have been an earlier existing prefix, hence EventTypeModify.
       
  5057     // Otherwise it is a new prefix.
       
  5058     TUint eventtype = (storedLifetime ? EventTypeModify : EventTypeAdd);
       
  5059 
       
  5060     const TUint two_hours = 7200; //2 * 60 * 60;  in seconds
       
  5061     if (aForce || aLifetime > two_hours || aLifetime > storedLifetime)
       
  5062         {
       
  5063         storedLifetime = aLifetime;
       
  5064         }
       
  5065     else if (storedLifetime >= two_hours || aLifetime >= storedLifetime)
       
  5066         {
       
  5067         storedLifetime = two_hours;
       
  5068         }
       
  5069     //
       
  5070     // If after above, the  storedLifetime > 0, then this prefix should
       
  5071     // still remain.
       
  5072     if (storedLifetime > 0)
       
  5073         {
       
  5074 
       
  5075         // Set new stored time, but watch out for overflow
       
  5076 
       
  5077         if (storedLifetime > KLifetimeForever - current_time)
       
  5078             prefix->iLifetime.iStored = KLifetimeForever;
       
  5079         else
       
  5080             prefix->iLifetime.iStored = current_time + storedLifetime;
       
  5081         //
       
  5082         // The iPreferred contains the duration of the "deprecated"
       
  5083         // time before true expiration occurs (in seconds)
       
  5084         //
       
  5085         //   0 <= iPreferred <= storedLifetime
       
  5086         //
       
  5087         if (aPreferred < storedLifetime)
       
  5088             prefix->iLifetime.iPreferred = storedLifetime - aPreferred;
       
  5089         else
       
  5090             prefix->iLifetime.iPreferred = 0;
       
  5091         prefix->iLifetime.iDeprecated = 0;
       
  5092 
       
  5093         // Set active timer only if the lifetime is less than "forever".
       
  5094         const TLifetime life = storedLifetime - prefix->iLifetime.iPreferred;
       
  5095         if (life < KLifetimeForever)
       
  5096             prefix->SetTimer(storedLifetime - prefix->iLifetime.iPreferred);
       
  5097         else
       
  5098             {
       
  5099             prefix->CancelTimer();
       
  5100             }
       
  5101 #ifdef SYMBIAN_TCPIPDHCP_UPDATE        
       
  5102         if(iGlobalflag)
       
  5103             {
       
  5104             //If the global flag is set(this will be set when the 'A' flag is set in the prefix of RA)
       
  5105             //then do DAD for the Global address
       
  5106             #ifdef _DEBUG
       
  5107                 LOG(Log::Printf(_L("<>\tCIp6Interface::SetPrefix() glbal flag is set")));
       
  5108             #endif
       
  5109             PerformDADForGlobalAddress(aPrefix,aLength);
       
  5110             iGlobalflag=EFalse;
       
  5111             }
       
  5112 #endif // SYMBIAN_TCPIPDHCP_UPDATE
       
  5113         // Send notification about new prefix to the event service
       
  5114         NotifyAddressEvent(eventtype, aPrefix, aLength, prefix, iAddress);
       
  5115         }
       
  5116     else
       
  5117         {
       
  5118         // Send notfification about deleted prefix to the event service
       
  5119         NotifyAddressEvent(EventTypeDelete, prefix->iPrefix, prefix->iLength,
       
  5120                 prefix, iAddress);
       
  5121 
       
  5122         iSequence++;
       
  5123         RemoveRoute(prefix);
       
  5124         }
       
  5125     }
       
  5126 
       
  5127 
       
  5128 void CIp6Interface::NotifyAddressEvent( TUint aEventType,
       
  5129                                         const TIp6Addr &aPrefix,
       
  5130                                         const TUint aLength,
       
  5131                                         const CIp6Route *aPrefixEntry,
       
  5132                                         const TIp6AddressInfo &aAddress ) const
       
  5133     /**
       
  5134     * Send notification about changed address to event manager.
       
  5135     * @param aEventType     The event type code (see in_bind.h).
       
  5136     * @param aPrefix        Prefix part of the address.
       
  5137     * @param aLength        Prefix length.
       
  5138     * @param aPrefixEntry   Pointer to the KRouteAdd_MYPREFIX entry in routing table
       
  5139     *                       NULL indicates this is was an addition of ID part of the
       
  5140     *                       address.
       
  5141     * @param aAddress       Information about the ID part of the address.
       
  5142     */
       
  5143     {
       
  5144     CIp6Manager *const mgr = &Interfacer();
       
  5145     
       
  5146     // If there is no event manager, or if there are no registered listeners, we can exit
       
  5147     // the function right away
       
  5148     if (!mgr->EventManager())
       
  5149         {
       
  5150         return;
       
  5151         }
       
  5152 
       
  5153     if (mgr->EventManager()->IsEmpty(EClassAddress))
       
  5154         {
       
  5155         return;
       
  5156         }
       
  5157   
       
  5158     TInetAddressInfo info;
       
  5159     info.iAddress = aPrefix;
       
  5160     if (aPrefixEntry)
       
  5161         {
       
  5162         MakeFullAddress(info.iAddress, aLength,
       
  5163             iAddress.iId.u.iAddr8, sizeof(iAddress.iId.u.iAddr8));
       
  5164         }
       
  5165     
       
  5166     TScopeType st = (TScopeType) (aPrefix.Scope() - 1);
       
  5167     info.iScopeId = Scope(st);
       
  5168     info.iPrefixLen = (TUint8) aLength;
       
  5169     info.iInterface = Index();
       
  5170     
       
  5171     TTime stamp;
       
  5172     stamp.UniversalTime();
       
  5173     const TLifetime current_time = ElapsedUnits(aAddress.iCreated, stamp);
       
  5174 
       
  5175     TLifetime plt, vlt;
       
  5176 
       
  5177     if (aAddress.iPLT != KLifetimeForever)
       
  5178         {
       
  5179         plt = (aAddress.iPLT > current_time) ?
       
  5180             aAddress.iPLT - current_time : 0 /* 0 = expired*/;
       
  5181         }
       
  5182     else
       
  5183         {
       
  5184         plt = KLifetimeForever;
       
  5185         }
       
  5186 
       
  5187     if (aAddress.iVLT != KLifetimeForever)
       
  5188         {
       
  5189         vlt = (aAddress.iVLT > current_time) ?
       
  5190             aAddress.iVLT - current_time : 0 /* 0 = expired*/;
       
  5191         }
       
  5192     else
       
  5193         {
       
  5194         vlt = KLifetimeForever;
       
  5195         }
       
  5196 
       
  5197     info.iPrefLifetime = plt / TIMER_UNIT;
       
  5198     info.iValidLifetime = vlt / TIMER_UNIT;
       
  5199     info.iGenerations = aAddress.iGenerated;
       
  5200     info.iNS = aAddress.iNS;
       
  5201     info.iState = (TUint8) aAddress.AddressState();
       
  5202     info.iType = (TUint8) aAddress.AddressType();
       
  5203     info.iFlags = 0;
       
  5204 
       
  5205     if (aPrefixEntry == NULL)
       
  5206         {
       
  5207         info.iFlags |= TInetAddressInfo::EF_Id;
       
  5208         if (plt == 0)
       
  5209             {
       
  5210             info.iFlags |= TInetAddressInfo::EF_Deprecated;
       
  5211             }
       
  5212         }
       
  5213     else
       
  5214         {
       
  5215         info.iFlags |= TInetAddressInfo::EF_Prefix;
       
  5216         if (aPrefixEntry->iLifetime.iDeprecated)
       
  5217             {
       
  5218             info.iFlags |= TInetAddressInfo::EF_Deprecated;
       
  5219             }
       
  5220         }
       
  5221 
       
  5222     mgr->EventManager()->Notify(EClassAddress, aEventType, &info);  
       
  5223     }
       
  5224 
       
  5225 //
       
  5226 // CIp6Interface::SetReachableTime
       
  5227 // *******************************
       
  5228 /**
       
  5229 // Compute the in use value for the reachable time. The
       
  5230 // value is stored in TickCount units!
       
  5231 //
       
  5232 // The iND is assumed to containt the base value in milliseconds
       
  5233 */
       
  5234 void CIp6Interface::SetReachableTime()
       
  5235     {
       
  5236     const TUint tick = TickPeriod();
       
  5237 
       
  5238     TReal factor = iND.iMinRandomFactor + Math::FRand(Interfacer().iSeed) * (iND.iMaxRandomFactor - iND.iMinRandomFactor);
       
  5239     (void)Math::Round(factor, (iND.iReachableTime * factor * 1000.0) / tick, 0);
       
  5240     (void)Math::Int((TInt32 &)iReachableTime, factor);
       
  5241     LOG(Log::Printf(_L("\tIF %u [%S] ReachableTime base=%d [ms], new time = %d [tics = %ds]"), iScope[0], &iName, iND.iReachableTime, iReachableTime, (TInt)((iReachableTime * tick) / 1000000)));
       
  5242     }
       
  5243 
       
  5244 // CIp6Interface::SetRetransTimer
       
  5245 // ******************************
       
  5246 /**
       
  5247 // Compute the in use value for the retrans timer. The value
       
  5248 // is stored in internal timer units.
       
  5249 //
       
  5250 // The iND is assumed to contain the base value in milliseconds
       
  5251 */
       
  5252 void CIp6Interface::SetRetransTimer()
       
  5253     {
       
  5254     iRetransTimer = CIp6Manager::TimerUnits(iND.iRetransTimer, 1000);
       
  5255     if (iRetransTimer == 0)
       
  5256         iRetransTimer = 1;  // Never allow ZERO!
       
  5257     LOG(Log::Printf(_L("\tIF %u [%S] RetransTimer base=%d, value = %u/%u s"),
       
  5258         iScope[0], &iName, iND.iRetransTimer, iRetransTimer, TIMER_UNIT));
       
  5259     }
       
  5260 
       
  5261 //
       
  5262 // CIp6Interface::SelectSource
       
  5263 // ***************************
       
  5264 /**
       
  5265 // Select and set the source address matching the
       
  5266 // specified destination address.
       
  5267 //
       
  5268 // @retval  aSrc    The selected source address.
       
  5269 // @param   aDst    The destination.
       
  5270 //
       
  5271 // @return
       
  5272 //  @li route pointer (MYPREFIX),   if source address is fully specified
       
  5273 //  @li NULL, if source address is not know or incomplete
       
  5274 */
       
  5275 CIp6Route *CIp6Interface::SelectSource(TIp6Addr &aSrc, const TIp6Addr &aDst) const
       
  5276     {
       
  5277     CIp6Route *best_match = NULL;
       
  5278     TInt best_score = KMinTInt;
       
  5279     const TUint scope = aDst.Scope();       // Prefetch destination scope
       
  5280     const TBool is_ip4 = aDst.IsV4Mapped(); // Prefetch destination type
       
  5281 
       
  5282     // If destination is my own address, the source address will
       
  5283     // be the destination address. Prepare for detecting this
       
  5284     // by prefetching the matching ID part, if any exists.
       
  5285     //
       
  5286     const TIp6AddressInfo *myid = IsMyId(aDst);
       
  5287     if (myid && !myid->IsAssigned())
       
  5288         myid = NULL;
       
  5289     //
       
  5290     // Choose the prefix part
       
  5291     //
       
  5292     for (CIp6Route *rt = iRouteList; rt != NULL; rt = rt->iNext)
       
  5293         {
       
  5294         if (!rt->IsMyPrefix())
       
  5295             continue;   // Not a "my prefix" entry, get next.
       
  5296         //
       
  5297         // The route entry represents a prefix entry
       
  5298         //
       
  5299         const TInt match = rt->iPrefix.Match(aDst) - rt->iLength;
       
  5300         if (myid && match >= 0)
       
  5301             {
       
  5302             // A quick hack to prevent choosing proxy or anycast
       
  5303             // address as a source address (they are currently
       
  5304             // entered as 128 bit adressess and "aDst ~ myid ~
       
  5305             // prefix"... -- msa
       
  5306             if (!myid->IsNormal())
       
  5307                 continue;
       
  5308             // The ID part of the destination has already matched,
       
  5309             // and now a full MYPREFIX matched => the destination
       
  5310             // is my own address on this interface,
       
  5311             // return aDst as a source!
       
  5312             aSrc = aDst;
       
  5313             return rt;
       
  5314             }
       
  5315         // For other than own addresses, consider the prefix only
       
  5316         // if the primary id length and this prefix have a compatible
       
  5317         // length... [somewhat kludgy way to prevent 2002:7f::/24 from
       
  5318         // being chosen over 2002:ip4::ip4/128 .. --msa]
       
  5319         // (make an exception for full 128 bit addresses)
       
  5320         if (rt->iLength < 128 && rt->iLength != iAddress.iPrefix)
       
  5321             continue;
       
  5322         // IPv4 addresses are currently stored as full 128 bit
       
  5323         // addresses, the IPv4 mapped test is only needed for them.
       
  5324         if (is_ip4 != (rt->iLength == 128 && rt->iPrefix.IsV4Mapped()))
       
  5325             continue;   // Mismatched IPv4 / IPv6!
       
  5326 
       
  5327         // Prefer matches that cover full prefix, thus use the difference
       
  5328         // between matched bits and prefix length as a criteria, with
       
  5329         // additional criteria that if the match is longer than prefix,
       
  5330         // the comparison value will be the prefix length.
       
  5331         // -- msa
       
  5332         TInt weight = match >= 0 ? rt->iLength : match;
       
  5333         if (rt->iLifetime.iDeprecated)
       
  5334             // A deprecated prefix. Consider it, but decrease it's comparison
       
  5335             // value by 128, so that it won't be selected if there is even one
       
  5336             // non-deprecated choice available.
       
  5337             weight -= 128;
       
  5338 
       
  5339         const TUint src_scope = rt->iPrefix.Scope();
       
  5340         if (src_scope < scope)
       
  5341             weight -= 256;  // use src with smaller scope only as last ditch.
       
  5342             
       
  5343         if (weight > best_score || (weight == best_score && src_scope == scope))
       
  5344             {
       
  5345             best_score = weight;
       
  5346             best_match = rt;
       
  5347             }
       
  5348         }
       
  5349     if (!best_match)
       
  5350         return NULL;    // Cannot find source address (no prefix!)
       
  5351 
       
  5352     // Kludge: if the prefix is 128 bits, use it as is for source address!
       
  5353     // However, there *SHOULD* be a corresponding address entry with
       
  5354     // id->iPrefix==0
       
  5355     if (best_match->iLength == 128)
       
  5356         {
       
  5357         for (const TIp6AddressInfo *id = &iAddress; ;id = &id->iNext->iInfo)
       
  5358             {
       
  5359             if (id->iPrefix == 0 && id->iId.IsEqual(best_match->iPrefix))
       
  5360                 {
       
  5361                 if (!id->IsAssigned())
       
  5362                     return NULL;
       
  5363                 aSrc = best_match->iPrefix;
       
  5364                 return best_match;
       
  5365                 }
       
  5366             if (id->iNext == NULL)
       
  5367                 break;
       
  5368             }
       
  5369         return NULL;
       
  5370         }
       
  5371     //
       
  5372     // Choose the id part
       
  5373     //
       
  5374     myid = NULL;
       
  5375     for (const TIp6AddressInfo *id = &iAddress; ;id = &id->iNext->iInfo)
       
  5376         {
       
  5377         if (id->IsAssigned() && id->IsNormal())
       
  5378             {
       
  5379             if (best_match->iLength <= id->iPrefix)
       
  5380                 {
       
  5381                 //
       
  5382                 // iGenerated is non-zero if id is randomly generated.
       
  5383                 // This may be used in privacy address.
       
  5384                 // Test
       
  5385                 //  iGenerated == 0, prefer random id
       
  5386                 //  iGenerated != 0, prefer non-random id.
       
  5387                 //
       
  5388                 if (myid == NULL)
       
  5389                     myid = id;
       
  5390                 else if (myid->iGenerated != 0)
       
  5391                     myid = id;
       
  5392                 }
       
  5393             }
       
  5394         if (id->iNext == NULL)
       
  5395             break;
       
  5396         }
       
  5397     if (myid)
       
  5398         {
       
  5399         aSrc = best_match->iPrefix;
       
  5400         MakeFullAddress(aSrc, best_match->iLength, myid->iId.u.iAddr8, sizeof(myid->iId.u.iAddr8));
       
  5401         return best_match;
       
  5402         }
       
  5403     return NULL;
       
  5404     }
       
  5405 
       
  5406 // CIp6Interface::UpdateIdRoutes
       
  5407 // *****************************
       
  5408 /**
       
  5409 // Maintains internal, address related route entries.
       
  5410 //
       
  5411 // Somewhat "ad hoc" code: maintain "solicited" node
       
  5412 // multicast addresses on the Route list for all id's.
       
  5413 // (the ad hoc part is in how this feature is activated
       
  5414 // by condition: 0 < aPrefix < 128, and only for IPv6.
       
  5415 //
       
  5416 // Also, maintain host loopback routes for configured
       
  5417 // alias addresses.
       
  5418 */
       
  5419 void CIp6Interface::UpdateIdRoutes(const TIp6AddressInfo &aId, const TLifetime aLifetime)
       
  5420     {
       
  5421     if (!aId.IsSet())
       
  5422         return; // Nothing to do with unspecified address.
       
  5423     if (aId.iPrefix == 0 && !aId.IsProxy())
       
  5424         {
       
  5425         const TUint flags = aId.IsAnycast() ? CIp6Route::EAnycast : CIp6Route::ELoopback;
       
  5426         (void)GetRoute(aId.iId, 128, flags, NULL, &aLifetime);
       
  5427         }
       
  5428 
       
  5429     // IPv6, each own id needs to recognize the corresponding solicited
       
  5430     // node multicast destination...
       
  5431     if (!aId.iId.IsV4Mapped() && aId.iPrefix < 128)
       
  5432         {
       
  5433         // ..or, should require that the Id part is at least
       
  5434         // 24 bits long, before solicited node is generated
       
  5435         // (iPrefix <= 104) -- msa
       
  5436         // Delete or Create entry (depending on aLifetime)
       
  5437         UpdateMulticast(TSolicitedNodeAddr(aId.iId), aLifetime);        
       
  5438         }
       
  5439         
       
  5440     // If this ID is being removed make sure all routes using this ID as a source
       
  5441     // address or prefix are also removed or else SelectSource will be confused if
       
  5442     // it tries to reuse a route which no longer has a corresponding source address.
       
  5443     if( aLifetime == 0 )
       
  5444         {
       
  5445         CIp6Manager &mgr = Interfacer();
       
  5446         CIp6Route *rt;
       
  5447 
       
  5448         for (CIp6Route **h = &iRouteList; ; )
       
  5449             {
       
  5450             rt = *h;
       
  5451             
       
  5452             if( !rt )
       
  5453                 {
       
  5454                 // Stop.
       
  5455                 break;
       
  5456                 }
       
  5457             else
       
  5458                 {
       
  5459                 if( aId.MatchExactly( rt->iAddress.Ip6Address() ) || aId.MatchExactly( rt->iPrefix ) )
       
  5460                     {
       
  5461                     // Remove the the route from the current position.
       
  5462                     *h = rt->iNext;
       
  5463                         
       
  5464                     LOG(rt->LogRoute(0));
       
  5465 
       
  5466                     //
       
  5467                     // Delete matching route, if lifetime is ZERO
       
  5468                     //
       
  5469                     if (rt->iIsRouter)
       
  5470                         {
       
  5471                         rt->iIsRouter = 0;
       
  5472                         RouterChanged(rt);
       
  5473                         }
       
  5474                     //
       
  5475                     // If any flows are attached to the route that is being removed,
       
  5476                     // move them all into the holding route with PENDING status.
       
  5477                     //
       
  5478                     // Note: holding is *ALWAYS* non-NULL. The only time holding
       
  5479                     // can be NULL, is when it is being created by InitL(), and in
       
  5480                     // that case GetRoute() *NEVER* gets into this branch! -- msa
       
  5481                     //
       
  5482                     mgr.MoveToHolding(*rt);
       
  5483 
       
  5484                     // Send notification about removed route to event manager
       
  5485                     NotifyRouteEvent(EventTypeDelete, rt);
       
  5486 
       
  5487                     delete rt;
       
  5488                     }
       
  5489                 else
       
  5490                     {
       
  5491                     h = &rt->iNext;
       
  5492                     }
       
  5493                 }
       
  5494             }
       
  5495         }
       
  5496     }
       
  5497 
       
  5498 
       
  5499 void CIp6Interface::NotifyMulticastEvent(TUint aEventType, const TIp6Addr &aMulticast, const TLifetime aLifetime) const
       
  5500 {
       
  5501     CIp6Manager *const mgr = &Interfacer();
       
  5502 
       
  5503     // If there is no event manager, or if there are no registered listeners, we can exit
       
  5504     // the function right away
       
  5505     if (!mgr->EventManager())
       
  5506         return;
       
  5507 
       
  5508     if (mgr->EventManager()->IsEmpty(EClassMulticast))
       
  5509         return;
       
  5510   
       
  5511     TInetMulticastInfo info;
       
  5512     info.iMulticastGroup = aMulticast;
       
  5513     info.iInterface = iScope[0];
       
  5514     info.iLifetime = aLifetime;
       
  5515 
       
  5516     mgr->EventManager()->Notify(EClassMulticast, aEventType, &info);
       
  5517 }
       
  5518 
       
  5519 
       
  5520 //
       
  5521 // CIp6Interface::SetId
       
  5522 // ********************
       
  5523 /**
       
  5524 // @retval  aId The address/id to be modified.
       
  5525 // @param   aAddr The new address.
       
  5526 // @param   aPrefix The length of the prefix part.
       
  5527 // @param   aAddressType Type of the address.
       
  5528 // @return
       
  5529 // @li 0, if ID was not changed
       
  5530 // @li 1, if ID changed
       
  5531 //
       
  5532 //  Although, the main point is the id-part, it is assumed that the
       
  5533 //  value stored as ID is also *ALWAYS* a valid full address for this
       
  5534 //  interface (some code may depend on it!)
       
  5535 */
       
  5536 TInt CIp6Interface::SetId(TIp6AddressInfo &aId, const TIp6Addr &aAddr, const TInt aPrefix, const TInt aAddressType)
       
  5537     {
       
  5538     // Should this also check whether address type is same?
       
  5539     // Changing just type does not work with this code!
       
  5540     // -- msa 24.10.2003
       
  5541     if (aId.IsSet() && aPrefix == aId.iPrefix && aAddr.IsEqual(aId.iId))
       
  5542         return 0;       // Id is same as before, no change!
       
  5543     if (aPrefix < 0 || aPrefix > 128)
       
  5544         return 0;       // Invalid length, do nothing!
       
  5545     if (TIp46Addr::Cast(aAddr).IsMulticast())
       
  5546         return 0;       // A multicast address cannot be my own.
       
  5547 
       
  5548     UpdateIdRoutes(aId, 0);     // Remove old route (if needed)
       
  5549     aId.iId = aAddr;
       
  5550     aId.iPrefix = (TUint8)aPrefix;
       
  5551     aId.SetInitial(NeedsND());
       
  5552     aId.SetType(aAddressType);
       
  5553     aId.iNS = 0;
       
  5554     aId.iCreated.UniversalTime();
       
  5555     aId.iVLT = KLifetimeForever;
       
  5556     aId.iPLT = KLifetimeForever;
       
  5557     UpdateIdRoutes(aId, KLifetimeForever);  // Add new route (if needed)
       
  5558 
       
  5559     // Send notification about the new address to the event service
       
  5560     NotifyAddressEvent(EventTypeAdd, aAddr, aPrefix, NULL, aId);
       
  5561 
       
  5562     // ..should activate Timeout for DAD detection!? -- mas
       
  5563 
       
  5564     return 1;   // Id has been changed
       
  5565     }
       
  5566 
       
  5567 TInt CIp6Interface::AddId(const TSockAddr& aId)
       
  5568     {
       
  5569     // Should get the true length of the id part. The code below works only
       
  5570     // for id with length of full bytes... -- msa
       
  5571     const TInt prefix = 128 - (*(TSockAddr *)&aId).GetUserLen() * 8;
       
  5572 
       
  5573     // Setting id of length ZERO (prefix == 128) does nothing
       
  5574     // and returns "nothing changed"...
       
  5575     if (prefix >= 0 /*&& prefix < 128*/)
       
  5576         {
       
  5577         TIp6Addr local(KInet6AddrLinkLocal);
       
  5578         //
       
  5579         // Add "ONLINK" route for all link locals
       
  5580         //
       
  5581         (void)GetRoute(local, 10, KRouteAdd_ONLINK);
       
  5582 
       
  5583         MakeFullAddress(local, prefix, aId.Ptr(), aId.Length());
       
  5584         // Need to set ID before prefix (SetPrefix does some checks that
       
  5585         // require a known id length on the interface...)
       
  5586         TInt ret = AddId(local, prefix);
       
  5587         // AddId is only used for IPv6 interfaces, add the link local "prefix"
       
  5588         // here. [totally add hoc rule: set the link local prefix only if
       
  5589         // idlen > 0!]
       
  5590         SetPrefix(local, prefix, 1);
       
  5591         return ret;
       
  5592         }
       
  5593     return 0;
       
  5594     }
       
  5595 //
       
  5596 // CIp6Interface::AddId
       
  5597 // ********************
       
  5598 /**
       
  5599 // This will define the primary ID, if not yet specified, or adds
       
  5600 // a new id.
       
  5601 */
       
  5602 TInt CIp6Interface::AddId(const TIp6Addr &aId, const TInt aPrefix, const TInt aAddressType, const TBool aForcePrimary)
       
  5603     {
       
  5604     ASSERT(!aId.IsUnspecified());
       
  5605     //
       
  5606     // First would need to check if any of the id's match for this address
       
  5607     //
       
  5608     TIp6AddressInfo *prevID = NULL, *id;
       
  5609     for (id = &iAddress; ;prevID = id, id = &id->iNext->iInfo)
       
  5610         {
       
  5611         // Compare id's as full addresses.
       
  5612         // Note: here comparing just address is correct. Address type
       
  5613         // can only be one of the following: normal, proxy, anycast, etc. 
       
  5614         if (id->IsSet() && id->iId.IsEqual(aId))
       
  5615             {
       
  5616             if( aForcePrimary && !id->IsPrimary() )
       
  5617                 {
       
  5618                 // We need to move this address into the primary slot.
       
  5619                 CIp6Address *oldPrimary = new CIp6Address;
       
  5620                 if (oldPrimary == NULL)
       
  5621                     return 0;
       
  5622                 oldPrimary->iInfo = iAddress;
       
  5623                 oldPrimary->iInfo.SetPrimary( EFalse );
       
  5624                 
       
  5625                 iAddress = *id;
       
  5626                 iAddress.SetPrimary( ETrue );
       
  5627                 iAddress.iIpv4LinkLocal = EFalse; // reset this flag in case a link local formerly occupied this slot
       
  5628                 iAddress.iNext = oldPrimary;
       
  5629                 
       
  5630                 if( prevID )
       
  5631                     {
       
  5632                     prevID->iNext = id->iNext;
       
  5633                     }
       
  5634                 delete id;
       
  5635 
       
  5636                 id = &iAddress;
       
  5637                 }
       
  5638                 
       
  5639             break;
       
  5640             }
       
  5641         if (id->iNext == NULL)
       
  5642             {
       
  5643             // None matched
       
  5644             //
       
  5645             if (!iAddress.IsSet())
       
  5646                 {
       
  5647                 // Primary ID slot is still empty, use it!
       
  5648                 id = &iAddress;
       
  5649                 iAddress.SetPrimary( ETrue );
       
  5650 
       
  5651                 break;
       
  5652                 }
       
  5653                 
       
  5654             //
       
  5655             // Primary id slot is used, need to create a new entry
       
  5656             //
       
  5657             if( aForcePrimary )
       
  5658                 {
       
  5659                 // We need to move this address into the primary slot.
       
  5660                 CIp6Address *oldPrimary = new CIp6Address;
       
  5661                 if (oldPrimary == NULL)
       
  5662                     return 0;
       
  5663                 oldPrimary->iInfo = iAddress;
       
  5664                 oldPrimary->iInfo.SetPrimary( EFalse );
       
  5665                 
       
  5666                 iAddress.SetPrimary( ETrue );
       
  5667                 iAddress.iIpv4LinkLocal = EFalse; // reset this flag in case a link local formerly occupied this slot
       
  5668                 iAddress.iNext = oldPrimary;
       
  5669 
       
  5670                 id = &iAddress;
       
  5671                 }
       
  5672             else
       
  5673                 {
       
  5674                 CIp6Address *p = new CIp6Address;
       
  5675                 if (p == NULL)
       
  5676                     return 0;
       
  5677                 p->iInfo.iNext = iAddress.iNext;
       
  5678 
       
  5679                 iAddress.iNext = p;
       
  5680 
       
  5681                 id = &p->iInfo;
       
  5682                 }
       
  5683 
       
  5684             break;
       
  5685             }
       
  5686         }
       
  5687     return SetId(*id, aId, aPrefix, aAddressType);
       
  5688     }
       
  5689 
       
  5690 // CIp6Interface::GetId
       
  5691 // ********************
       
  5692 // Locate Id block by address
       
  5693 TIp6AddressInfo* CIp6Interface::GetId(const TIp6Addr &aAddr) const
       
  5694     {
       
  5695     for (const TIp6AddressInfo *id = &iAddress; ;id = &id->iNext->iInfo)
       
  5696         {
       
  5697         // Compare id's as full addresses
       
  5698         if (id->IsSet() && aAddr.IsEqual(id->iId))
       
  5699             // Throw away 'const' -- hopefully this does not cause any
       
  5700             // compiler problems... -- msa
       
  5701             return (TIp6AddressInfo *)id;
       
  5702         if (id->iNext == NULL)
       
  5703             break;  // None found!
       
  5704         }
       
  5705     return NULL;
       
  5706     }
       
  5707 
       
  5708 //
       
  5709 // CIp6Interface::RemId
       
  5710 // ********************
       
  5711 // Remove specified Id.
       
  5712 TInt CIp6Interface::RemId(const TIp6AddressInfo *const aId)
       
  5713     {
       
  5714     if (aId == NULL) // For convenience, allow call with NULL ptr.
       
  5715         return KErrNotFound;
       
  5716 
       
  5717     UpdateIdRoutes(*aId, 0);        // Remove old route (if needed)
       
  5718     ++iSequence;                    // Always increment (does not hurt, even if no deletion actually happens)
       
  5719 
       
  5720     // Note: event is generated, even if no matching address is found
       
  5721     NotifyAddressEvent(EventTypeDelete, aId->iId, aId->iPrefix, NULL, *aId);
       
  5722 
       
  5723     if (aId == &iAddress)
       
  5724         {
       
  5725         //
       
  5726         // Removing the primary Id is a special case
       
  5727         //
       
  5728         if (iAddress.IsTentative())
       
  5729             iAddress.SetDuplicate();
       
  5730         else
       
  5731             iAddress.SetNoAddress();
       
  5732         return KErrNone;
       
  5733         }
       
  5734 
       
  5735     CIp6Address **h, *p;
       
  5736     for (h = &iAddress.iNext; (p = *h) != NULL; h = &p->iInfo.iNext)
       
  5737         if (aId == &p->iInfo)
       
  5738             {
       
  5739             *h = p->iInfo.iNext;
       
  5740             delete p;
       
  5741             return KErrNone;
       
  5742             }
       
  5743     return KErrNotFound;
       
  5744     }
       
  5745 
       
  5746 
       
  5747 //
       
  5748 // GetIp4Config
       
  5749 // ************
       
  5750 /**
       
  5751 // A simple code that initializes the TSoInetIfConfig structure
       
  5752 // properly and performs the query to the interface. Not a general
       
  5753 // method, but just way to minimize code size (used from different
       
  5754 // places)
       
  5755 */
       
  5756 static TInt GetIp4Config(CNifIfBase *aIf, TPckgBuf<TSoInetIfConfig> &cfg)
       
  5757     {
       
  5758     TSoInetIfConfig *const c = &cfg();
       
  5759 
       
  5760     c->iFamily = KAfInet;
       
  5761 
       
  5762     // Ip4 interfaces are picky about the family constant,
       
  5763     // and TInetAddr initialize into family KAfInet6.
       
  5764     // The following will turn them into KAfInet
       
  5765     // -- msa
       
  5766     c->iConfig.iAddress.SetAddress(0);
       
  5767     c->iConfig.iNetMask.SetAddress(0);
       
  5768     c->iConfig.iDefGate.SetAddress(0);
       
  5769     c->iConfig.iBrdAddr.SetAddress(~0U);
       
  5770     c->iConfig.iNameSer1.SetAddress(0);
       
  5771     c->iConfig.iNameSer2.SetAddress(0);
       
  5772     return aIf ? aIf->Control(KSOLInterface, KSoIfConfig, cfg) : KErrNotFound;
       
  5773     }
       
  5774 
       
  5775 
       
  5776 // CIp6Interface::IsMyId
       
  5777 // *********************
       
  5778 TIp6AddressInfo *CIp6Interface::IsMyId(const TIp6Addr &aAddr) const
       
  5779     {
       
  5780     //
       
  5781     // Find longest matching and usable id (the length of the id is "128 - iPrefix").
       
  5782     //
       
  5783     const TIp6AddressInfo *best_id = NULL;
       
  5784     for (const TIp6AddressInfo *id = &iAddress; ;id = &id->iNext->iInfo)
       
  5785         {
       
  5786         if ((best_id == NULL || best_id->iPrefix < id->iPrefix) &&
       
  5787             id->IsSet() &&
       
  5788             id->Match(aAddr))
       
  5789             {
       
  5790             best_id = id;
       
  5791             }
       
  5792         if (id->iNext == NULL)
       
  5793             break;
       
  5794         }
       
  5795     // Throw away 'const'
       
  5796     return (TIp6AddressInfo *)best_id;
       
  5797     }
       
  5798 
       
  5799 // CIp6Interface::IsMyPrefix
       
  5800 // *************************
       
  5801 CIp6Route *CIp6Interface::IsMyPrefix(const TIp6Addr &aAddr, const TIp6AddressInfo &aId) const
       
  5802     {
       
  5803     for (const CIp6Route *rt = iRouteList; rt != NULL; rt = rt->iNext)
       
  5804         {
       
  5805         if (!rt->IsMyPrefix())
       
  5806             continue;
       
  5807         // The prefix is examined, only if
       
  5808         //  aId.iPrefix == 128 (0x80,  special, id length is 0, any prefix will do), or
       
  5809         //  aId.iPrefix == 0 (0x00, id is full address, just pick any matching prefix)
       
  5810         //  aId.iPrefix == rt->iLength (otherwise, id and prefix must have matching lengths).
       
  5811         if ((aId.iPrefix & 0x7f) != 0 && aId.iPrefix != rt->iLength)
       
  5812             continue;   // id must be zero length or match the prefix length.
       
  5813         if (rt->iPrefix.Match(aAddr) >= rt->iLength)
       
  5814             return (CIp6Route *)rt;
       
  5815         }
       
  5816     return NULL;
       
  5817     }
       
  5818 
       
  5819 //
       
  5820 // CIp6Interface::IsMyAddress
       
  5821 // **************************
       
  5822 /**
       
  5823 // IsMyAddress returns non-NULL, if aAddr matches any of the
       
  5824 // current addresses for this interface
       
  5825 */
       
  5826 TIp6AddressInfo *CIp6Interface::IsMyAddress(const TIp6Addr &aAddr, const TInt aAll) const
       
  5827     {
       
  5828     //
       
  5829     // First would need to check if any of the id's match for this address
       
  5830     // (and only properly assigned id can be "my address")
       
  5831     //
       
  5832     TIp6AddressInfo *id = IsMyId(aAddr);
       
  5833     if (id == NULL || !id->IsAssigned())
       
  5834         return NULL;
       
  5835     //
       
  5836     // proxy/anycast address are not normal "my addresses"
       
  5837     // (they cannot be used as a source address)
       
  5838     //
       
  5839     if (aAll == 0 && !id->IsNormal())
       
  5840         return NULL;
       
  5841     //
       
  5842     // If id part is 128 bits, then no further tests are required,
       
  5843     // and otherwise need to check that address matches some prefix.
       
  5844     //
       
  5845     if (id->iPrefix == 0 || IsMyPrefix(aAddr, *id))
       
  5846         return id;  // This is my address!
       
  5847     //
       
  5848     // None of the prefixes match
       
  5849     //
       
  5850     return NULL;
       
  5851     }
       
  5852 //
       
  5853 // CIp6Interface::IsForMeAddress
       
  5854 // *****************************
       
  5855 TBool CIp6Interface::IsForMeAddress(const TIp6Addr &aAddr) const
       
  5856     {
       
  5857     //
       
  5858     // IsForMeAddress is TRUE. if the address is IsMyAddress or matches
       
  5859     // any of the "multicast" addresses configured for the interface
       
  5860     // (for IPv4 "multicast" includes the broadcast addresses). This
       
  5861     // is logically two different passes over the iRouteList, but as
       
  5862     // this method is expected to be used a lot, the both loops have
       
  5863     // been merged here... -- msa
       
  5864 
       
  5865 
       
  5866     // First check if any of the id's match for this address. If none
       
  5867     // matches, then only the "multicast" addresses need to be
       
  5868     // tested.
       
  5869     const TIp6AddressInfo *id = IsMyId(aAddr);
       
  5870     if (id == NULL || !id->IsAssigned() || id->IsProxy())
       
  5871         // Not yet assigned or is a proxy address (not really for me)
       
  5872         id = NULL;
       
  5873     else if (id->iPrefix == 0)
       
  5874         // Full configured address matched, no need for further tests
       
  5875         return TRUE;
       
  5876 
       
  5877     // Examine ELoopback entries in the route list for match
       
  5878     for (const CIp6Route *rt = iRouteList; rt != NULL; rt = rt->iNext)
       
  5879         {
       
  5880         if (rt->iState != CIp6Route::ELoopback)
       
  5881             continue;           // Not my prefix or multicast...
       
  5882         if (rt->iIsMulticast)
       
  5883             {
       
  5884             // "Multicast" entries are always specified as 128 bit
       
  5885             // prefixes => use IsEqual, which is faster than Match!
       
  5886             if (aAddr.IsEqual(rt->iPrefix))
       
  5887                 return TRUE;    // Matched fully a multicast, it's for me!
       
  5888             }
       
  5889         else if (id)
       
  5890             {
       
  5891             // Prefixes need to be compared only if Id matched!
       
  5892             if (rt->iPrefix.Match(aAddr) >= rt->iLength)
       
  5893                 return TRUE;    // Matched a prefix and id, it's my address!
       
  5894             }
       
  5895         }
       
  5896     return FALSE;   // No match, not for me!
       
  5897     }
       
  5898 
       
  5899 //
       
  5900 // CIp6Interface::SetMtu
       
  5901 // *********************
       
  5902 /**
       
  5903 // SetMtu *defines* the current send MTU for the link, and
       
  5904 // updates the Path MTU in case it is obviously affected.
       
  5905 */
       
  5906 void CIp6Interface::SetMtu(TInt aMtu, TInt aMin)
       
  5907     {
       
  5908     iSMtu = aMtu;
       
  5909     //
       
  5910     // This may not be the correct solution, but assume
       
  5911     // this method is not called often (and usually only
       
  5912     // on startup), thus assume that this can be used to
       
  5913     // initiate the Path MTU discovery and set the path
       
  5914     // MTU same local link mtu [currently the only way
       
  5915     // to get larger than minimum path mtu] -- msa
       
  5916     //
       
  5917     // *NOTE*
       
  5918     //      Flows are not notified of this! [hopefully
       
  5919     //      the caller will do something about it].
       
  5920     if (aMtu >= aMin && (iPMtu < aMin || iPMtu > aMtu))
       
  5921         iPMtu = aMtu;
       
  5922     LOG(Log::Printf(_L("\tIF %u [%S] Proposed MTu=%d, current Send MTU=%d, Recv MTU=%d, Path MTU=%d"), iScope[0], &iName, aMtu, iSMtu, iRMtu, iPMtu));
       
  5923     }
       
  5924 
       
  5925 // MaskLength
       
  5926 // **********
       
  5927 // Local utility, compute consecutive leftmost 1-bits from 32 bit integer
       
  5928 //
       
  5929 // Not optimized for speed or anything...
       
  5930 //
       
  5931 static TInt MaskLength(TUint32 aAddr)
       
  5932     {
       
  5933     TInt count = 0;
       
  5934     // obviously, this is "brute force" counting
       
  5935     while (aAddr & 0x80000000)
       
  5936         {
       
  5937         count++;
       
  5938         aAddr <<= 1;
       
  5939         }
       
  5940     return count;
       
  5941     }
       
  5942 static TInt MaskLength(const TIp6Addr &aAddr)
       
  5943     {
       
  5944     TInt count = 0;
       
  5945     TUint loopCount = sizeof(aAddr.u.iAddr8) / sizeof(aAddr.u.iAddr8[0]);
       
  5946     for (TUint i = 0; i < loopCount; ++i)
       
  5947         if (aAddr.u.iAddr8[i] == 0xFF)
       
  5948             count += 8;
       
  5949         else
       
  5950             {
       
  5951             count += MaskLength(aAddr.u.iAddr8[i] << 24);
       
  5952             break;
       
  5953             }
       
  5954     return count;
       
  5955     }
       
  5956 
       
  5957 // CIp6Interface::Update6
       
  5958 // **********************
       
  5959 // Configure interface for IPv6 if it supports KSoIfInfo6 
       
  5960 TInt CIp6Interface::Update6(TInt aTransition)
       
  5961     {
       
  5962     if (iIsIPv6)
       
  5963         return aTransition;     // Do not redo configuration!
       
  5964 
       
  5965     // Error returns from the following query is an indication
       
  5966     // that the driver does not support IPv6.
       
  5967     TPckgBuf<TSoIfInfo6> ifProp;
       
  5968     ASSERT(iNifIf != NULL);
       
  5969     if (iNifIf->Control(KSOLInterface, KSoIfInfo6, ifProp) != KErrNone)
       
  5970         return aTransition; // No IPv6 support, exit
       
  5971 
       
  5972     iFeatures = ifProp().iFeatures;
       
  5973     iSpeedMetric = ifProp().iSpeedMetric;
       
  5974     SetMtu(ifProp().iMtu, KInet6MinMtu);
       
  5975     iRMtu = ifProp().iRMtu;
       
  5976 
       
  5977     TPckgBuf<TSoInet6IfConfig> cfg;
       
  5978     cfg().iFamily = KAfInet6;
       
  5979     if (iNifIf->Control(KSOLInterface, KSoIfConfig, cfg) != KErrNone)
       
  5980         return aTransition; // No IPv6 support, exit
       
  5981 
       
  5982     iIsIPv6 = 1;    // Ok, configure for IPv6
       
  5983     aTransition = KIfaceTransition_UP;
       
  5984 
       
  5985     if (iFeatures & KIfCanMulticast)
       
  5986         {
       
  5987         CIp6Route *route;
       
  5988         // If interface indicates multicast capability, then add a default
       
  5989         // multicast route for it (to allow join group to select this
       
  5990         // interface!)
       
  5991         route = GetRoute(KInet6AddrAllNodes, 8, KRouteAdd_ONLINK);
       
  5992         if (route && (iFeatures & KIfIsLoopback))
       
  5993           {
       
  5994             // Multicast routes on loopback interfaces should have poor metric.
       
  5995             // If a "real" network interface comes up, it should be favoured over loopback.
       
  5996             route->iMetric = KLoopbackMcastMetric;
       
  5997           }
       
  5998         }
       
  5999 
       
  6000     if (cfg().iLocalId.Family() != KAFUnspec)
       
  6001         (void)AddId(cfg().iLocalId);
       
  6002 
       
  6003     if (cfg().iRemoteId.Family() != KAFUnspec)
       
  6004         {
       
  6005         // Assume the interface is giving implicitly an address
       
  6006         // of some other host on the link (probably a Point-to-Point
       
  6007         // link, and this is the other end of the link). Just construct
       
  6008         // a link local address for it and setup a host route.
       
  6009         //
       
  6010         TIp6Addr remote(KInet6AddrLinkLocal);
       
  6011         MakeFullAddress(remote, 10, cfg().iRemoteId.Ptr(), cfg().iRemoteId.Length());
       
  6012         (void)GetRoute(remote, 128, KRouteAdd_ONLINK);
       
  6013         }
       
  6014 
       
  6015     // Initialize name servers from configuration
       
  6016     UpdateNameServers(cfg().iNameSer1, cfg().iNameSer2);
       
  6017 
       
  6018     //
       
  6019     // Add permanent multicast groups
       
  6020     //
       
  6021     (void)GetRoute(KInet6AddrNodeLocal, 128, KRouteAdd_MYPREFIX);
       
  6022 #if 0
       
  6023     (void)UpdateMulticast(KInet6AddrAllNodes);
       
  6024 #else
       
  6025     if (iScope[1])  // Interface has link local scope id?
       
  6026         (void)UpdateMulticast(KInet6AddrAllNodes);
       
  6027 #endif
       
  6028     return aTransition;
       
  6029     }
       
  6030 
       
  6031 // CIp6Interface::ConfigureAddress
       
  6032 // *******************************
       
  6033 /**
       
  6034 // Internal utility which configures an first/additional IPv4
       
  6035 // address + netmask for the interface
       
  6036 //
       
  6037 // @param aAddr
       
  6038 //  The IPv4 address in IPv4-mapped format
       
  6039 // @param aMaskLength
       
  6040 //  The netmask length (bits counted for IPv6, thus netmask
       
  6041 //  is configured only if <tt>96 < aMaskLength <= 128</tt>.
       
  6042 //
       
  6043 // @return
       
  6044 //  @li = 0, if no change in configuration
       
  6045 //  @li = 1, if configuration changed
       
  6046 */
       
  6047 TInt CIp6Interface::ConfigureAddress(const TIp6Addr &aAddr, const TUint aMaskLength, const TBool aForcePrimary)
       
  6048     {
       
  6049     ASSERT(aMaskLength <= 128);
       
  6050     if (aMaskLength > 128)
       
  6051         return 0;
       
  6052 
       
  6053 #ifdef _LOG
       
  6054     TLogAddressPrefix tmp(aAddr, aMaskLength);
       
  6055     Log::Printf(_L("\tIF %u [%S] ConfigureAddress([%S])"), iScope[0], &iName, &tmp);
       
  6056 #endif
       
  6057 
       
  6058     // Address can be configured only if there is an address...
       
  6059     if (aAddr.u.iAddr32[3] == 0)
       
  6060         return 0;
       
  6061 
       
  6062     //
       
  6063     // Setup up my own address
       
  6064     // -----------------------
       
  6065     // Convert TInetAddr iAddress into ipv4 compat address
       
  6066     // and set it up as a prefix and id
       
  6067 
       
  6068     if (AddId(aAddr, 0, TIp6AddressInfo::ENormal, aForcePrimary) == 0)
       
  6069         // No change.
       
  6070         return 0;
       
  6071 
       
  6072     // Setup up netmask (if defined)
       
  6073     // -----------------------------
       
  6074     if (aMaskLength > 96)
       
  6075         {
       
  6076         //
       
  6077         // Add ONLINK route for the net
       
  6078         //
       
  6079         (void)GetRoute(aAddr, aMaskLength, KRouteAdd_ONLINK);
       
  6080         //
       
  6081         // Make network broadcast address as a "multicast group" into the routes.
       
  6082         // my_net is the network prefix combined with all-ones host part (= broadcast address)
       
  6083         TIp46Addr my_net(0xffffffffU >> (aMaskLength-96));
       
  6084         my_net.u.iAddr32[3] |= aAddr.u.iAddr32[3];
       
  6085         CIp6Route *const rt = GetRoute(my_net, 128, KRouteAdd_MYPREFIX);
       
  6086         if (rt)
       
  6087             rt->iIsMulticast = 1;   // mark it as "multicast"!
       
  6088         }
       
  6089     return 1;
       
  6090     }
       
  6091 
       
  6092 
       
  6093 // CIp6Interface::FindInternalIpv4LinkLocalAddr
       
  6094 // ****************************************
       
  6095 /**
       
  6096 // Find the one and only internally generated IPv4 link-local, if present.
       
  6097 //
       
  6098 // @return the TIp6AddressInfo, if such address exists; and NULL otherwise.
       
  6099 */
       
  6100 TIp6AddressInfo* CIp6Interface::FindInternalIpv4LinkLocalAddr()
       
  6101     {
       
  6102     // Call does not get ownership of object.
       
  6103     return const_cast<TIp6AddressInfo *>( FindIpv4LinkLocalAddr() );
       
  6104     }
       
  6105 
       
  6106 
       
  6107 // CIp6Interface::RandomAddress
       
  6108 // ****************************
       
  6109 // Generate pseudorandom IPv4 link local address.
       
  6110 TInt CIp6Interface::RandomAddress(TIp6Addr &aAddr, TUint aPrefix, TUint aN)
       
  6111     {
       
  6112     // Use current hardware address as a seed and generate N'th variant.
       
  6113     // Optimized for space, not speed (wasting CPU on generating
       
  6114     // the N-1 numbers needlessly, but saving the need to store
       
  6115     // the seed in CIp6Interface...).
       
  6116     //
       
  6117     // *NOTE 1* In current use aN is stored in TUint8 of
       
  6118     // TIp6AddressInfo::iGenerated => after 256 addressesses,
       
  6119     // the same sequence starts, and the loop below does not
       
  6120     // grow into infinity... (in practice aN = 0 or 1)
       
  6121     // *NOTE 2* To avoid the loop, one would need to store
       
  6122     // two seeds into CIp6Interface, one for IPv4 and one for
       
  6123     // IPv6.
       
  6124     //
       
  6125     // The use of hw as seed gives the effect that host tends to
       
  6126     // get the same link local address, if possible
       
  6127     TInt64 seed = (TInt64 &)iHwAddr[8];
       
  6128     TReal r;
       
  6129     TUint i = 0;
       
  6130     do
       
  6131         r = Math::FRand(seed);
       
  6132     while (++i <= aN);  // pick N'th pseudo-random number
       
  6133 
       
  6134 
       
  6135     if (aAddr.IsV4Mapped())
       
  6136         {
       
  6137         if (aAddr.Scope() != KIp6AddrScopeLinkLocal)
       
  6138             return 0;   // IPv4 address can only be generated if Link Local
       
  6139 
       
  6140         TReal random_addr_float;
       
  6141         TInt32 random_addr = 0;
       
  6142 
       
  6143         (void)Math::Round(random_addr_float, r * (INET_ADDR(169,254,254,255) - INET_ADDR(169,254,1,0)), 0);
       
  6144         (void)Math::Int(random_addr, random_addr_float);
       
  6145         TIp46Addr addr(INET_ADDR(169,254,1,0) + random_addr);
       
  6146 
       
  6147         aAddr = addr;
       
  6148         return 1;
       
  6149         }
       
  6150     //
       
  6151     // For IPv6, a placeholder for now -- just use the current seed as a source for the ID part
       
  6152     // (this part is not used until privacy, RFC-3041 is implemented)
       
  6153     //
       
  6154     MakeFullAddress(aAddr, aPrefix, (TUint8 *)&seed, sizeof(seed));
       
  6155     return 1;
       
  6156     }
       
  6157 
       
  6158 // CIp6Interface::DuplicateAddress
       
  6159 // *******************************
       
  6160 // The specified address has been detected as duplicate.
       
  6161 void CIp6Interface::DuplicateAddress(TIp6AddressInfo *aId, TBool &aDefendIPAddress, TBool aGratuitousArp)
       
  6162     {
       
  6163     if (aId == NULL)
       
  6164         return;
       
  6165     TIp6Addr addr = aId->iId;
       
  6166     for (;;)
       
  6167         {
       
  6168         TTime stamp;
       
  6169         stamp.UniversalTime();
       
  6170 
       
  6171         if (!aId->IsTentative())
       
  6172             {
       
  6173             //
       
  6174             // Messy situation, a collision on established address. The
       
  6175             // following logic is applied: if address is younger than
       
  6176             // DupAddrDefendTime seconds, give it up. Otherwise defend
       
  6177             // address by sending an announcement. However, to prevent looping
       
  6178             // on this, reset creation time of the address to now.
       
  6179             //
       
  6180             TLifetime now = ElapsedUnits(aId->iCreated, stamp);
       
  6181             if (now > CIp6Manager::TimerUnits(iND.iDupAddrDefendTime))
       
  6182                 {
       
  6183                 if(aGratuitousArp)
       
  6184                 {
       
  6185                 aDefendIPAddress = ETrue;
       
  6186                 }
       
  6187                 else 
       
  6188                 {
       
  6189                 // Old established address, try to keep it: reset
       
  6190                 // creation time and send an announcement for it...
       
  6191                 aId->iCreated = stamp;
       
  6192                 (void)SendNeighbors(KInet6ICMP_NeighborSol, NULL, aId->iId);
       
  6193                 }
       
  6194                 return;
       
  6195                 }
       
  6196             }
       
  6197         //
       
  6198         // A tentative address or an established address which we
       
  6199         // going to give up...
       
  6200         // 
       
  6201         if (aId->iGenerated == 0)
       
  6202             break;  // Not automatically generated or has been generated
       
  6203                     // too many times already!
       
  6204         if (!RandomAddress(addr, aId->iPrefix, aId->iGenerated))
       
  6205             break;  // failed for some reason
       
  6206         //
       
  6207         // A new address has been generated
       
  6208         //
       
  6209         aId->iGenerated++;
       
  6210         SetId(*aId, addr, aId->iPrefix, aId->AddressType());
       
  6211         if (aId->iGenerated >= iND.iMaxAddrRegenerations)
       
  6212             // If we have exceeded the limitation of regenerations,
       
  6213             // then put the creation time 60sec into future, and thus
       
  6214             // delay the activation of this address (probes start
       
  6215             // at least 60s delayed).
       
  6216             aId->iCreated += TTimeIntervalSeconds(60);
       
  6217         //
       
  6218         // Start the DAD process
       
  6219         //
       
  6220         Timeout(stamp);
       
  6221         return;
       
  6222         }
       
  6223     //
       
  6224     // No new address, remove the duplicate
       
  6225     //
       
  6226     RemId(aId);
       
  6227     }
       
  6228 
       
  6229 // CIp6Interface::ConfigureLinkLocal
       
  6230 // *********************************
       
  6231 /**
       
  6232 // Internal utility for automatic configuring of the linklocal IPv4 address.
       
  6233 //
       
  6234 // @param aConfAddr IPv4 address received from CNifIfBase::Control(). If 0, no IPv4 address
       
  6235 //                  was configured on Nif, and linklocal address will be enabled on settings
       
  6236 //                  2 (EV4LLConditional) and 1 (EV4LLAlways).
       
  6237 //
       
  6238 // @return
       
  6239 // @li  = 0, if no change in configuration
       
  6240 // @li  = 1, if configuration changed
       
  6241 */
       
  6242 TInt CIp6Interface::ConfigureLinkLocal(TUint32 aConfAddr)
       
  6243     {
       
  6244     // IPv4 link local specification applies only for
       
  6245     // interfaces that support Neighbour Discovery).
       
  6246     if (!NeedsND())
       
  6247         return 0;
       
  6248         
       
  6249     // Always support IPv4 LL on all ND interfaces, by
       
  6250     // always installing the IPv4 LL onlink route.
       
  6251     const TInt prefix = 96+16; // Ipv4-mapped format, need to add 96
       
  6252     TIp46Addr addr(KInetAddrLinkLocalNet);
       
  6253     if (GetRoute(addr, prefix, KRouteAdd_ONLINK) == NULL)
       
  6254         {
       
  6255         // If this route cannot be created or does not exist,
       
  6256         // there is no point in doing anything else here.
       
  6257         return 0;
       
  6258         }
       
  6259 
       
  6260     // Check if automatic configuration has already been done,
       
  6261     TIp6AddressInfo *const exists = FindInternalIpv4LinkLocalAddr();
       
  6262 
       
  6263     // Currently, detecting duplicates is only defined for
       
  6264     // interfaces that support ARP, and this is only possible if
       
  6265     // there are link layer addresses.
       
  6266     // => LinkLocals can only be generated on interface
       
  6267     //    which has addresses!
       
  6268     const TInt flag = HaveIp4LinkLocal();
       
  6269     if (flag == EV4LLDisabled ||
       
  6270         (flag == EV4LLConditional && aConfAddr) ||
       
  6271         iHwAddr.Family() == KAFUnspec)
       
  6272         {
       
  6273         // The automatically configured IPv4 should not exist - remove
       
  6274         // if it does. RemId can be called with NULL, and returns
       
  6275         // KErrNone, if address was actually removed.
       
  6276         TInt retVal = RemId(exists);
       
  6277         
       
  6278         #ifdef _LOG
       
  6279             if( retVal == KErrNone )
       
  6280                 {
       
  6281                 TBuf<39> addrStr;
       
  6282                 
       
  6283                 TInetAddr( addr, 0 ).Output( addrStr );
       
  6284                 
       
  6285                 Log::Printf( _L( "CIp6Interface::ConfigureLinkLocal - Link local address %S removed" ), &addrStr );
       
  6286                 }
       
  6287         #endif
       
  6288             
       
  6289         return retVal;
       
  6290         }
       
  6291 
       
  6292     if (exists)
       
  6293         {
       
  6294         // Just reset the lifetimes, in case it was in deprecated status
       
  6295         exists->iPLT = KLifetimeForever;
       
  6296         exists->iVLT = KLifetimeForever;
       
  6297         return 0;
       
  6298         }
       
  6299     //
       
  6300     // Address does not exist yet - make it unless we are trying to reuse
       
  6301     // an old address.
       
  6302     //
       
  6303     if( RandomAddress(addr, prefix, 0) && ConfigureAddress( addr, prefix ) )
       
  6304         {
       
  6305         // If address generated, must find the address and
       
  6306         // mark it as generated.
       
  6307         TIp6AddressInfo *const id = GetId(addr);
       
  6308         if (id)
       
  6309             {
       
  6310             id->iIpv4LinkLocal = 1;     // Mark it as Internally Generated IPv4 LL.
       
  6311             if (id->iGenerated == 0)
       
  6312                 id->iGenerated = 1;
       
  6313             // Add a random constant to the creation time, so that DAD starts after a random
       
  6314             // delay. [timers 1sec accuracy is a bit problem here -- msa]
       
  6315             ASSERT(iND.iIPv4RetransTimer < 2000);   // ensures non-negative adjust below.
       
  6316             id->iCreated += TTimeIntervalMicroSeconds32((TInt)(Math::FRand(Interfacer().iSeed) * iND.iIPv4RetransTimer * 1000000.0));
       
  6317 
       
  6318             #ifdef _LOG
       
  6319                 TBuf<39> addrStr;
       
  6320                 
       
  6321                 TInetAddr( addr, 0 ).Output( addrStr );
       
  6322                 
       
  6323                 Log::Printf( _L( "CIp6Interface::ConfigureLinkLocal - Link local address %S configured" ), &addrStr );
       
  6324             #endif
       
  6325             }
       
  6326         return 1;
       
  6327         }
       
  6328     return 0;
       
  6329     }
       
  6330 
       
  6331 CIp6Route *CIp6Interface::StartProbeND(const TIp6Addr &aSrc, const TIp6Addr &aDst)
       
  6332     /**
       
  6333     * Probe for an address on the link.
       
  6334     *
       
  6335     * Starts a probing neighbour discovery on a destination address.
       
  6336     * This can be used to force ND on any address.
       
  6337     *
       
  6338     * @param    aSrc    Source address to be used in probing
       
  6339     * @param    aDst    Destination to probe
       
  6340     * @return
       
  6341     *   Host route entry, if probing started (or was already active).
       
  6342     *   Or, NULL not started.
       
  6343     */
       
  6344     {
       
  6345     CIp6Route *const n = GetRoute(aDst, 128, KRouteAdd_PROBINGONLY);
       
  6346     if (n && n->iIsProbing)
       
  6347         {
       
  6348 #ifdef _LOG
       
  6349         TLogAddressPrefix dst(aDst);
       
  6350         TLogAddressPrefix src(aSrc);
       
  6351         Log::Printf(_L("\tIF %u [%S] StartProbeND(src=%S, dst=%S)"), iScope[0], &iName, &src, &dst);
       
  6352 #endif
       
  6353         n->StartND(aSrc);
       
  6354         return n;
       
  6355         }
       
  6356     return NULL;
       
  6357     }
       
  6358 
       
  6359 
       
  6360 
       
  6361 // CIp6Interface::UpdateNameServers
       
  6362 // ********************************
       
  6363 /**
       
  6364 // Internal utility to load the namer server addresses consistently
       
  6365 // @param ns1 The name server address 1.
       
  6366 // @param ns2 The name server address 2.
       
  6367 // @param aOverride
       
  6368 //  @li == 0 => addresses are only changed if unspecified previously
       
  6369 //  @li != 0 => new specified address always overwrites previous setting
       
  6370 */
       
  6371 void CIp6Interface::UpdateNameServers(const TInetAddr &ns1, const TInetAddr &ns2, const TInt aOverride)
       
  6372     {
       
  6373 #ifdef _LOG
       
  6374     TLogAddressPrefix old_ns(ns1);
       
  6375     TLogAddressPrefix new_ns(ns2);
       
  6376     Log::Printf(_L("\tIF %u [%S] UpdateNameServers(ns1=%S, ns2=%S, override=%d)"), iScope[0], &iName, &old_ns, &new_ns, aOverride);
       
  6377     old_ns.Set(iNameSer1);
       
  6378 #endif
       
  6379     //
       
  6380     // 1. name server address
       
  6381     //
       
  6382     if (ns1.Family() != KAFUnspec && (aOverride || iNameSer1.Family() == KAFUnspec))
       
  6383         {
       
  6384         if (ns1.IsUnspecified())
       
  6385             iNameSer1.Init(KAFUnspec);
       
  6386         else
       
  6387             iNameSer1 = ns1;
       
  6388         }
       
  6389 #ifdef _LOG
       
  6390     new_ns.Set(iNameSer1);
       
  6391     Log::Printf(_L("\tIF %u [%S]   ns1: old=%S new=%S"), iScope[0], &iName, &old_ns, &new_ns);
       
  6392     old_ns.Set(iNameSer2);
       
  6393 #endif
       
  6394     //
       
  6395     // 2. name server address
       
  6396     //
       
  6397     if (ns2.Family() != KAFUnspec && (aOverride || iNameSer2.Family() == KAFUnspec))
       
  6398         {
       
  6399         if (ns2.IsUnspecified())
       
  6400             iNameSer2.Init(KAFUnspec);
       
  6401         else
       
  6402             iNameSer2 = ns2;
       
  6403         }
       
  6404 #ifdef _LOG
       
  6405     new_ns.Set(iNameSer2);
       
  6406     Log::Printf(_L("\tIF %u [%S]   ns2: old=%S new=%S"), iScope[0], &iName, &old_ns, &new_ns);
       
  6407 #endif
       
  6408     }
       
  6409 
       
  6410 //
       
  6411 // CIp6Interface::Update4
       
  6412 // **********************
       
  6413 // Configure interface for IPv4 if it supports KSoIfInfo and KSoIfConfig
       
  6414 TInt CIp6Interface::Update4(TInt aTransition)
       
  6415     {
       
  6416     if (iIsIPv4)
       
  6417         return aTransition; // Do not redo configuration, if it has been already done!
       
  6418 
       
  6419     TPckgBuf<TSoIfInfo> info_buf;
       
  6420     ASSERT(iNifIf != NULL);
       
  6421     TInt err = iNifIf->Control(KSOLInterface, KSoIfInfo, info_buf);
       
  6422     if (err != KErrNone)
       
  6423         return aTransition; // No IPv4 support (no change)
       
  6424     //
       
  6425     // Basic minimal configuration
       
  6426     //
       
  6427 
       
  6428     const TSoIfInfo &info = info_buf();
       
  6429     iFeatures = info.iFeatures;
       
  6430     iSpeedMetric = info.iSpeedMetric;
       
  6431     SetMtu(info.iMtu, KInetMinMtu);
       
  6432     iRMtu = info.iMtu;  // In IPv4 there is no separate slot for
       
  6433                         // receive and send MTU (assume they are same)
       
  6434 
       
  6435     // Need to magically setup routing for the IPv4 interfaces,
       
  6436     // just ask the interface parameters and make best effort...
       
  6437     TPckgBuf<TSoInetIfConfig> cfg;
       
  6438     if ((err = GetIp4Config(iNifIf, cfg)) != KErrNone)
       
  6439         return aTransition; // No IPv4 support
       
  6440 
       
  6441     // For all IPv4 Interfaces, setup 255.255.255.255 address
       
  6442     static const TIp6Addr broadcast = {{{0,0,0,0,0,0,0,0,0,0,0xff,0xff,255,255,255,255}}};
       
  6443     CIp6Route *const rt = GetRoute(broadcast, 128, KRouteAdd_MYPREFIX);
       
  6444     if (rt)
       
  6445         rt->iIsMulticast = 1;   // mark it as "multicast"
       
  6446 
       
  6447     // For all IPv4 Interfaces: join to 224.0.0.1 multicast group (all hosts)
       
  6448     static const TIp6Addr mc_hosts = {{{0,0,0,0,0,0,0,0,0,0,0xff,0xff,224,0,0,1}}};
       
  6449     (void)UpdateMulticast(mc_hosts);
       
  6450     if ((iFeatures & (KIfCanMulticast|KIfIsLoopback)) == KIfCanMulticast)
       
  6451         {
       
  6452         // Add default IPv4 multicast route (but not on loopbacks!)
       
  6453         // (this puts all multicast as "ONLINK", instead of possibly
       
  6454         // punting them to the default gateway!)
       
  6455         (void)GetRoute(mc_hosts, 100, KRouteAdd_ONLINK);
       
  6456         }
       
  6457 
       
  6458     //  cfg().iConfig values:
       
  6459     //
       
  6460     const TInetIfConfig  &cf = cfg().iConfig;
       
  6461     const TUint32 addr = cf.iAddress.Address();
       
  6462     const TIp46Addr my_addr(addr);
       
  6463 
       
  6464     // Initialize name servers from configuration
       
  6465     UpdateNameServers(cf.iNameSer1, cf.iNameSer2);
       
  6466 
       
  6467     // Configure "configured" address, if any, and configure ZEROCONF link local
       
  6468     // address (if not already done).  Only the EV4LLAlways and EV4LLConditional
       
  6469     // with no static IP address options cause link local creation at this time.
       
  6470     // A configuration daemon may create a link local at its discretion (e.g.,
       
  6471     // if DHCP discovery fails) if the EV4LLConfigDaemonControlled option
       
  6472     // is enabled.
       
  6473     TInt changed = ConfigureAddress(my_addr, 96+MaskLength(cf.iNetMask.Address()));
       
  6474     const TInt flag = HaveIp4LinkLocal();
       
  6475     if( flag != EV4LLConfigDaemonControlled ) // daemon with EV4LLConfigDaemonControlled interface option will use KSoInetCreateIPv4LLOnInterface socket option to configure a link local if desired
       
  6476         {
       
  6477         changed |= ConfigureLinkLocal( addr );
       
  6478         }
       
  6479     if (changed == 0)
       
  6480         return aTransition; // -- no change in update4
       
  6481 
       
  6482     iIsIPv4 = 1;    // Freeze current configuration and mark IF as IPv4 capable
       
  6483 
       
  6484     const TUint32 defgate = cf.iDefGate.Address();
       
  6485     if (defgate)
       
  6486         {
       
  6487         const TIp46Addr tmp(defgate);   // tmp required to get it compiled with gcc!
       
  6488         if (defgate == addr)
       
  6489             {
       
  6490             // *NOTE* Apparently some GPRS phones have a PPP server which gives
       
  6491             // my own address as a default gateway, do not add gateway route
       
  6492             // in such case (it might confuse next hop selection).
       
  6493             //
       
  6494             // *NOTE* This branch is only entered when the interface reports
       
  6495             // "broken/bad" configuration information (unless we define the
       
  6496             // condition "gateway == my address" to mean exactly this: install
       
  6497             // default IPv4 onlink route to the link).
       
  6498             (void)GetRoute(tmp, 96, KRouteAdd_ONLINK);
       
  6499             }
       
  6500         else
       
  6501             {
       
  6502             const TInetAddr gateway(tmp, 0);
       
  6503             (void)GetRoute(tmp, 128, KRouteAdd_ISROUTER);
       
  6504             (void)GetRoute(tmp, 96, KRouteAdd_GATEWAY, &gateway);
       
  6505             }
       
  6506         }
       
  6507 #if 0   // iBrdAddr appears to hold the other end address??
       
  6508 
       
  6509     //  TInetAddr iBrdAddr. Store net broadcast address into
       
  6510     // iPrefix[0]... (so it will be recognized as own...)
       
  6511     cf.iBrdAddr.ConvertToV4Mapped();
       
  6512     iPrefix[0] = TIp6Prefix(cf.iBrdAddr.Ip6Address(), 128);
       
  6513 #endif
       
  6514 
       
  6515     return KIfaceTransition_UP;
       
  6516     }
       
  6517 
       
  6518 // CIp6Interface::SendNeighbors
       
  6519 // ****************************
       
  6520 const TInt KSendNeighbors_NO_OVERRIDE = 0x100;  // Do not set OVERRIDE bit in NA
       
  6521 /**
       
  6522 // Send Neighbor Discovery packets (IPv6 ND or IPv4 ARP).
       
  6523 //
       
  6524 // Internal help method which is used to send send one of the
       
  6525 // following
       
  6526 //  @li Neighbor Solicitation
       
  6527 //  @li Neighbor Advertisement
       
  6528 //  @li Router Solicitation
       
  6529 //
       
  6530 // to the interface
       
  6531 //
       
  6532 // @param aMessageType
       
  6533 //  The low 8 bits are the ICMP6 type code of the message to be sent
       
  6534 //  The higher bits can be used as flags for details
       
  6535 // @param aDest
       
  6536 //  The (host) route to be used in sending. This is used for unicast
       
  6537 //  ND traffic. If NULL, then packet will have multicast destination.
       
  6538 // @param aTarget
       
  6539 //  The target address (used in NS/NA).
       
  6540 // @param aSource
       
  6541 //  The source address to use. If not given (NULL or unspecified), the source is
       
  6542 //  selected by the destination (for ND) or by the aTarget (for ARP) address.
       
  6543 // @return
       
  6544 //  @li == KErrNone, if send apparently succeeded
       
  6545 //  @li != KErrNone, for problems detected (out of memory mostly)
       
  6546 //
       
  6547 // WARNING:
       
  6548 //  This code is "hand tailored" to work exactly and *ONLY* with the listed
       
  6549 //  types of ICMP messages. If a support for a new type of ICMP is to be
       
  6550 //  added, the code must be reviewed very carefully! -- msa
       
  6551 */
       
  6552 TInt CIp6Interface::SendNeighbors(TInt aMessageType, CIp6Route *aDest, const TIp6Addr &aTarget, const TIp6Addr *const aSource)
       
  6553     {
       
  6554 #ifdef SYMBIAN_TCPIPDHCP_UPDATE  
       
  6555     #ifdef _DEBUG
       
  6556         LOG(Log::Printf(_L("<>\tCIp6Interface::SendNeighbors()")));
       
  6557     #endif 
       
  6558 #endif // SYMBIAN_TCPIPDHCP_UPDATE  
       
  6559     const TUint8 icmp_type = (TUint8)aMessageType;
       
  6560     RMBufSendPacket packet;
       
  6561     RMBufSendInfo *info = NULL;
       
  6562     TInt err = KErrNone;
       
  6563     TIp6Addr dst, src;
       
  6564 
       
  6565 #ifdef ARP
       
  6566     // If the target is IPv4 address, then translate the IPv6 ND request to
       
  6567     // ARP message.
       
  6568     if (aTarget.IsV4Mapped())
       
  6569         {
       
  6570         // The ARP kludge needs only to map the Neighbor Solicitation
       
  6571         // into ARP Request (this really should not get called with
       
  6572         // anything else).
       
  6573         if (icmp_type != KInet6ICMP_NeighborSol)
       
  6574             return KErrNone;
       
  6575 
       
  6576         //
       
  6577         // Source address is actually used in the ARP packet and
       
  6578         // must thus match the ARP target. Thus, select it by
       
  6579         // target.
       
  6580         if (aSource && (aSource->u.iAddr32[3] == 0 || IsMyAddress(*aSource)))
       
  6581             src = *aSource;
       
  6582         else if (SelectSource(src, aTarget) == NULL)
       
  6583             src = KInet6AddrNone;
       
  6584 
       
  6585         const TUint arp_length = TInet6HeaderArp::MinHeaderLength() +
       
  6586             (iHwAddr.GetUserLen() + 4) * 2;
       
  6587         TRAP(err, info = packet.CreateL(arp_length));
       
  6588         if (err != KErrNone || info == NULL)
       
  6589             return err;
       
  6590         for (;;)
       
  6591             {
       
  6592             TInet6Packet <TInet6HeaderArp> arp;
       
  6593             arp.Set(packet, 0, arp_length);
       
  6594             if (arp.iHdr == NULL)
       
  6595                 break;
       
  6596             arp.iHdr->SetPrAddrLen(4);
       
  6597             arp.iHdr->SetHwAddrLen(iHwAddr.GetUserLen());
       
  6598             // Assume the required ARP Hardware type is returned in the port
       
  6599             // field of the hardware address of the interface (either this,
       
  6600             // or the interface snoops ARP and fixes the value for this
       
  6601             // field.. -- msa)
       
  6602             arp.iHdr->SetHardwareType(iHwAddr.Port());
       
  6603             arp.iHdr->SetProtocolType(KArpProtocolType_IP);
       
  6604             arp.iHdr->SetOperation(EArpOperation_REQUEST);
       
  6605             arp.iHdr->SenderHwAddr().Copy(iHwAddr.Address());
       
  6606             arp.iHdr->TargetHwAddr().FillZ();
       
  6607             // Assume src & target are IPv4 mapped address...
       
  6608             arp.iHdr->SenderPrAddr().Copy(TPtrC8(&src.u.iAddr8[12], 4));
       
  6609             arp.iHdr->TargetPrAddr().Copy(TPtrC8(&aTarget.u.iAddr8[12], 4));
       
  6610             info->iProtocol = KProtocolArp;
       
  6611             info->iFlags = 0;
       
  6612             // Note: if aDest is non-NULL, then this iDstAddr will be
       
  6613             // will be replaced in aDest->Send() with the link layer
       
  6614             // address... -- msa
       
  6615             TInetAddr::Cast(info->iDstAddr).SetAddress(KInetAddrBroadcast);
       
  6616             TInetAddr::Cast(info->iSrcAddr).SetAddress(0);  // Don't care
       
  6617             packet.Pack();
       
  6618             // draft-ietf-zeroconf-ipv4-linklocal-05.txt says that whenever
       
  6619             // the sender is ipv4 link local, then the replies (and requests)
       
  6620             // must always be sent to the broadcast address [IMHO, this is
       
  6621             // a bit dubious rule, but if it is so specified, comply... -- msa]
       
  6622             if (aDest && src.Scope() != KIp6AddrScopeLinkLocal)
       
  6623                 aDest->Send(packet);
       
  6624             else if (iState == EFlow_READY)
       
  6625                 {
       
  6626                 // Send only if ready, to avoid queuing ARP packets into hold queue.
       
  6627                 Send(packet, NULL);
       
  6628                 }
       
  6629             break;
       
  6630             }
       
  6631         packet.Free();
       
  6632         return KErrNone;
       
  6633         }
       
  6634 #endif
       
  6635     //
       
  6636     // If destination is Unspecified, use solicited node address generated from
       
  6637     // the target address (as first default, may be changed later below)
       
  6638     //
       
  6639     if (aDest)
       
  6640         dst = aDest->iPrefix;
       
  6641     else
       
  6642         dst = (const TIp6Addr)TSolicitedNodeAddr(aTarget);
       
  6643     //
       
  6644     // Try to pick aSrc address, if not specified by the caller
       
  6645     // Leave it unspecified, if no valid source addresses.
       
  6646     //
       
  6647     if (aSource && (aSource->IsUnspecified() || IsMyAddress(*aSource)))
       
  6648         // However, a source address must be a valid address on this interface
       
  6649         // or unspecified (it cannot be a proxy or anycast). Thus, IsMyAddress
       
  6650         // test in above. [This situation occurs when node is acting as
       
  6651         // a router/proxy and is trying to find destination cache for a
       
  6652         // forwarded packet, by normal rules the source is taken from the
       
  6653         // packet.
       
  6654         // Could perhaps do this test before calling SendNeighbors? --msa]
       
  6655         src = *aSource;
       
  6656     else if (SelectSource(src, dst) == NULL)
       
  6657         src = KInet6AddrNone;
       
  6658     // This allocates too much space for the RS, but as class
       
  6659     // used in TInet6Checksum is NA, the mapping would fail
       
  6660     // for too short RMBufChain... icky! -- msa
       
  6661     // [but, as one RMBuf is always needed anyway, it doesn't
       
  6662     // cause any real extra allocations either...]
       
  6663     TUint icmp_length = TInet6HeaderICMP_NeighborAdv::MinHeaderLength();
       
  6664     for (;;)    // for handy error exits via breaks...
       
  6665         {
       
  6666         TInt link_layer = 0;    // The length of the SLL/TLL option in bytes
       
  6667         if (iHwAddr.Family() != KAFUnspec && !src.IsUnspecified())
       
  6668             {
       
  6669             // Got Link Layer Address, include it into the solicitation
       
  6670             link_layer = ((iHwAddr.GetUserLen() + 2) + 7) & ~0x7;
       
  6671             icmp_length += link_layer;
       
  6672             }
       
  6673 
       
  6674         TRAP(err, info = packet.CreateL(icmp_length));
       
  6675         if (err != KErrNone || info == NULL)
       
  6676             break;
       
  6677 
       
  6678         ASSERT((TUint)info->iLength == icmp_length);
       
  6679 
       
  6680         TInet6Checksum<TInet6HeaderICMP_NeighborAdv> icmp(packet);
       
  6681         if (icmp.iHdr == NULL)
       
  6682             break;      // Shouldn't happen!
       
  6683         //
       
  6684         // Build the ICMP Message
       
  6685         //
       
  6686         icmp.iHdr->SetType(icmp_type);
       
  6687         icmp.iHdr->SetCode(0);
       
  6688         icmp.iHdr->SetParameter(0); // (for NA, this may contain flags, see below)
       
  6689         switch (icmp_type)
       
  6690             {
       
  6691             case KInet6ICMP_NeighborAdv:
       
  6692 #ifdef SYMBIAN_TCPIPDHCP_UPDATE                  
       
  6693                 #ifdef _DEBUG
       
  6694                     LOG(Log::Printf(_L("<>\tCIp6Interface::SendNeighbors() KInet6ICMP_NeighborAdv is called")));
       
  6695                 #endif
       
  6696 #endif // SYMBIAN_TCPIPDHCP_UPDATE                      
       
  6697                 // Make some guesses for S and O bits of NA (these
       
  6698                 // depend on how this SendNeighbors method is called
       
  6699                 // in the current implementation!) -- msa
       
  6700                 //
       
  6701                 if (aDest)
       
  6702                     {
       
  6703                     // Assume NA to a specific destionation
       
  6704                     // is always SOLICITED!
       
  6705                     icmp.iHdr->SetS(1);
       
  6706                     }
       
  6707                 else
       
  6708                     {
       
  6709                     // Otherwise dest is allways for all nodes
       
  6710                     dst = KInet6AddrAllNodes;
       
  6711                     }
       
  6712                 if ((KSendNeighbors_NO_OVERRIDE & aMessageType) == 0)
       
  6713                     {
       
  6714                     // By default all NA's are for own address, so O=1, if we
       
  6715                     // have link_layer addr (unless disabled by the caller).
       
  6716                     // (NA's proxy addresses must not have O set, for example)
       
  6717                     icmp.iHdr->SetO(link_layer);
       
  6718                     }
       
  6719                 icmp.iHdr->SetR(iIsRouter);
       
  6720                 // *FALL TRHOUGH TO NS*/
       
  6721             case KInet6ICMP_NeighborSol:
       
  6722 #ifdef SYMBIAN_TCPIPDHCP_UPDATE                  
       
  6723                 #ifdef _DEBUG
       
  6724                     LOG(Log::Printf(_L("<>\tCIp6Interface::SendNeighbors() KInet6ICMP_NeighborSol is called")));
       
  6725                 #endif
       
  6726 #endif // SYMBIAN_TCPIPDHCP_UPDATE                      
       
  6727                 icmp.iHdr->Target() = aTarget;  // NS & NA have same format for this
       
  6728                 break;
       
  6729             case KInet6ICMP_RouterSol:
       
  6730                 if (aDest == NULL)
       
  6731                     // Unspecific destination is always to all ROUTERS
       
  6732                     dst = KInet6AddrAllRouters;
       
  6733                 // Argh! because we allocated too much space for the
       
  6734                 // buffer, the info->iLength is now incorrect for RS.
       
  6735                 // Need to fix.. another yech! -- msa
       
  6736                 icmp_length -=
       
  6737                     TInet6HeaderICMP_NeighborAdv::MinHeaderLength() -
       
  6738                     TInet6HeaderICMP_RouterSol::MinHeaderLength();
       
  6739                 packet.TrimEnd(icmp_length);
       
  6740                 break;
       
  6741             default:
       
  6742                 ASSERT(0);
       
  6743                 break;
       
  6744             }
       
  6745         //
       
  6746         // Add Target (for NA) or Source (for NS and RS) Link-layer address option (if possible)
       
  6747         //
       
  6748         if (link_layer > 0)
       
  6749             {
       
  6750             const TPtr8 ptr(((RMBufPacketPeek &)packet).Access(link_layer, info->iLength - link_layer));
       
  6751             if (ptr.Length() < link_layer)
       
  6752                 break;
       
  6753             TInet6OptionICMP_LinkLayer *addr = (TInet6OptionICMP_LinkLayer *)ptr.Ptr();
       
  6754             addr->SetType(icmp_type == KInet6ICMP_NeighborAdv ? KInet6OptionICMP_TargetLink : KInet6OptionICMP_SourceLink);
       
  6755             addr->SetLength(link_layer >> 3);    // Option length is in units of 8 octets!
       
  6756             addr->Address().Copy(iHwAddr.Address());
       
  6757             }
       
  6758         //
       
  6759         // Complete the Info structure for ICMP Checksum computation
       
  6760         //
       
  6761         info->iProtocol = KProtocolInet6Icmp;
       
  6762         TInetAddr::Cast(info->iDstAddr).SetAddress(dst);
       
  6763         TInetAddr::Cast(info->iSrcAddr).SetAddress(src);
       
  6764         TInetAddr::Cast(info->iDstAddr).SetScope(iScope[dst.Scope()-1]);    // scopeid from current interface
       
  6765 
       
  6766         // Create unconnected flow context to the packet (info)
       
  6767         if (info->iFlow.Open(iNifUser->iNetwork, info->iProtocol) != KErrNone)
       
  6768             break;
       
  6769         CIp6Flow *flow = (CIp6Flow *)info->iFlow.FlowContext();
       
  6770         if (!flow)
       
  6771             break;
       
  6772         // Setup the connection information and connect
       
  6773         info->iFlow.SetRemoteAddr(info->iDstAddr);
       
  6774         info->iFlow.SetLocalAddr(info->iSrcAddr);
       
  6775         info->iFlow.SetIcmpType(icmp_type, 0);
       
  6776         flow->iInfo.iLocalSet = 1;              // Disable source address select (even for unspecified)
       
  6777         flow->iInfo.iLockId = iScope[0];        // Accept connect only to this interface.
       
  6778         flow->iInfo.iLockType = EScopeType_IF;  // Accept connect only to this interface.
       
  6779         flow->iOptions.iMulticastHops = 255;    // ND wants hoplimit = 255 for multicast
       
  6780         flow->iOptions.iHopLimit = 255;         // ND wants hoplimit = 255 for unicast
       
  6781         flow->iOptions.iMulticastLoop = 0;      // We don't want to see own packets!
       
  6782         flow->iOptions.iKeepInterfaceUp = 0;    // We don't keep IF up just for ND traffic.
       
  6783         info->iFlow.Connect();
       
  6784         if (flow->iStatus != KErrNone)
       
  6785             {
       
  6786             LOG(Log::Printf(_L("\tIF  %d [%S] SendNeighbors connect failed (%d)"), iScope[0], &iName, (TInt)flow->iStatus));
       
  6787             info->iFlow.Close();
       
  6788             break;      // Cannot get a flow opened..
       
  6789             }
       
  6790         // The "assert" below might seem logical, but it is not, if ND is
       
  6791         // to IPSEC VPN interface (VPN != Real interface for flow).
       
  6792         // -- thus, remove it!
       
  6793         // __ASSERT_DEBUG(iNifIf == info->iFlow.Interface(), User::Panic(_L("DEBUG"), 0));
       
  6794 
       
  6795         info->iFlags = 0;
       
  6796         icmp.ComputeChecksum(packet, info);
       
  6797         packet.Pack();
       
  6798         (void)iNifUser->iNetwork->Send(packet, NULL);
       
  6799         LOG(Log::Printf(_L("<>\tCIp6Interface::SendNeighbors() KInet6ICMP_NeighborSol is connected")));
       
  6800         return KErrNone;
       
  6801         //  
       
  6802         }   // <-- Never get here, not a real loop!
       
  6803     packet.Free();
       
  6804     LOG(Log::Printf(_L("\tIF %u [%S] SendNeighbors send failed (%d)"), iScope[0], &iName, err));
       
  6805     return err < 0 ? err : KErrNoMemory;
       
  6806     }
       
  6807 
       
  6808 
       
  6809 //
       
  6810 // CIp6Interface::StartSending
       
  6811 // ***************************
       
  6812 // Interface specific StartSending method. Generic code (and IPv6 stuff)
       
  6813 TInt CIp6Interface::StartSending()
       
  6814     {
       
  6815     if (!iNifIf)
       
  6816         return KErrGeneral;         // Should never happen!?
       
  6817 
       
  6818     // Getting a StartSending from a device means that the driver
       
  6819     // is ready for the first or more input. Thus, by default set
       
  6820     // the interface state initially to EFlow_READY. The code
       
  6821     // after this may decide to set some other state later.
       
  6822     //
       
  6823     // Similarly, decide on initial return value for the
       
  6824     // transition state
       
  6825     TInt transition = (iState > 0) ? KIfaceTransition_READY : KIfaceTransition_NONE;
       
  6826     iState = EFlow_READY;
       
  6827 
       
  6828     //
       
  6829     // If there are any packets in hold queue, then flush out
       
  6830     // as many as possible now...
       
  6831     //
       
  6832     if (!iHoldQueue.IsEmpty())
       
  6833         {
       
  6834         RMBufChain packet;
       
  6835         TInt count = 0;
       
  6836         while (iHoldQueue.Remove(packet))
       
  6837             {
       
  6838             count++;
       
  6839             // Use the standard Send() method! This has a code to re-insert the packet
       
  6840             // into hold queue (but, it will not fire as long as iState is not
       
  6841             // EFlow_HOLD!)
       
  6842             (void)Send(packet);
       
  6843             if (iState > 0)
       
  6844                 {
       
  6845                 // The interface went back to hold, ignore start sending
       
  6846                 LOG(Log::Printf(_L("\tIF %u [%S] NIF signals HOLD after sending %d packets from hold queue (%d)"),
       
  6847                     iScope[0], &iName, count, (TInt)iHoldQueue.IsEmpty()));
       
  6848                 return KIfaceTransition_NONE;
       
  6849                 }
       
  6850             }
       
  6851         LOG(Log::Printf(_L("\tIF %u [%S] Flushed hold queue (%d) successfully"), iScope[0], &iName, count));
       
  6852         }
       
  6853 
       
  6854     // Configure Network and IAP identifiers
       
  6855     TPckgBuf<TSoIfConnectionInfo> netinfo;
       
  6856     if (iNifIf->Control(KSOLInterface, KSoIfGetConnectionInfo, netinfo) == KErrNone)
       
  6857         {
       
  6858         // NIF supports Network Information
       
  6859         LOG(Log::Printf(_L("\tIF %u [%S] has IAP=%d, NET=%d"),
       
  6860             iScope[0], &iName, (TInt)netinfo().iIAPId, (TInt)netinfo().iNetworkId));
       
  6861         }
       
  6862     else
       
  6863         {
       
  6864         // NIF does not support Network Information, pick some dummies
       
  6865         netinfo().iIAPId = ~iScope[0];
       
  6866         netinfo().iNetworkId = KDefaultNetworkId;
       
  6867         LOG(Log::Printf(_L("\tIF %u [%S] has no ConnectionInfo, defaulting IAP=%d, NET=%d"),
       
  6868             iScope[0], &iName, (TInt)netinfo().iIAPId, (TInt)netinfo().iNetworkId));
       
  6869         }
       
  6870     //
       
  6871     // Initialize the scope vector from netinfo
       
  6872     //
       
  6873     iScope[1] = netinfo().iIAPId; // - Link Local Scope (2)
       
  6874     iScope[2] = netinfo().iIAPId; // - Subnet-local Scope (3)
       
  6875     // Remaining slots will get the network id
       
  6876     for (TInt i = 3; i <= EScopeType_NET; ++i)
       
  6877         iScope[i] = netinfo().iNetworkId;
       
  6878 
       
  6879     //
       
  6880     // Refresh the hardware address of the interface on each StartSending
       
  6881     // (if link layer addresses are supported by the interface)
       
  6882     //
       
  6883     TPckgBuf<TSoIfHardwareAddr> hwaddr;
       
  6884     if (iNifIf->Control(KSOLInterface, KSoIfHardwareAddr, hwaddr) == KErrNone)
       
  6885         iHwAddr = TLinkAddr::Cast(hwaddr().iHardwareAddr);
       
  6886     else
       
  6887         iHwAddr.SetFamily(KAFUnspec);
       
  6888 
       
  6889     transition = Update4(transition);
       
  6890     transition = Update6(transition);
       
  6891 
       
  6892     if (transition == KIfaceTransition_UP)
       
  6893         {
       
  6894         //
       
  6895         // Save the UP transition time into the iAddress.iPreferredLifetime
       
  6896         // and activate router finding and duplicate address detection.
       
  6897         //
       
  6898         //
       
  6899         // Before sending the solicitations, choose a delay [0..MAX_RTR_SOLICITATION_DELAY]
       
  6900         //
       
  6901         const TInt delay = (TInt)(Math::FRand(Interfacer().iSeed) * iND.iMaxRtrSolicitationDelay * 1000000.0);
       
  6902         iAddress.iCreated += TTimeIntervalMicroSeconds32(delay);
       
  6903         LOG(Log::Printf(_L("\tIF %u [%S] Next event delay=%d [us]"), iScope[0], &iName, delay));
       
  6904         iAddress.iNS = 0;
       
  6905         iRetryRS = 0;
       
  6906         Interfacer().SetTimerWithUnits(iTimeout, CIp6Manager::TimerUnits(delay, 1000000));
       
  6907 
       
  6908         // This is treated as a change-type event, the add event is considered to occur
       
  6909         // in DoBind (i.e. when InterfaceAttached is called)
       
  6910         NotifyInterfaceEvent(EventTypeModify);
       
  6911         }
       
  6912 
       
  6913     return transition;
       
  6914     }
       
  6915 
       
  6916 
       
  6917 void CIp6Interface::NotifyInterfaceEvent(TUint aEventType) const
       
  6918 {
       
  6919     CIp6Manager *const mgr = &Interfacer();
       
  6920 
       
  6921     // If there is no event manager, or if there are no registered listeners, we can exit
       
  6922     // the function right away
       
  6923     if (!mgr->EventManager())
       
  6924         return;
       
  6925 
       
  6926     if (mgr->EventManager()->IsEmpty(EClassInterface))
       
  6927         return;
       
  6928   
       
  6929     TInetInterfaceInfo info;
       
  6930 
       
  6931     info.iIndex = iScope[0];
       
  6932     info.iHwAddr = iHwAddr;
       
  6933     info.iName = iName;
       
  6934     info.iFeatures = iFeatures;
       
  6935     info.iSMtu = iSMtu;
       
  6936     info.iRMtu = iRMtu;
       
  6937     info.iSpeedMetric = iSpeedMetric;
       
  6938 
       
  6939     // Copied and edited from interfaceinfo()
       
  6940     if (iNifIf == NULL)
       
  6941         info.iState = EIfDown; // no interface or address not known or was duplicate
       
  6942     else if (iState == EFlow_READY)
       
  6943         info.iState = EIfUp;
       
  6944     else if (iState == EFlow_PENDING)
       
  6945         info.iState = EIfPending;
       
  6946     else if (iState == EFlow_HOLD)
       
  6947         info.iState = EIfBusy;
       
  6948 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
  6949     else if (iState == EFlow_NOTCONFIGURE)
       
  6950         info.iState = EIfNotConfigured;
       
  6951 #endif //SYMBIAN_TCPIPDHCP_UPDATE    
       
  6952     else
       
  6953         info.iState = EIfDown;
       
  6954 
       
  6955     mgr->EventManager()->Notify(EClassInterface, aEventType, &info);
       
  6956 }
       
  6957 
       
  6958 
       
  6959 //
       
  6960 // CIp6Interface::Timeout()
       
  6961 // ************************
       
  6962 //
       
  6963 void CIp6Interface::Timeout(const TTime &aStamp)
       
  6964     {
       
  6965     // Somewhat twisted logic for sending RS and NS, but not wanting to run
       
  6966     // separate timers for both, and as they have different transmit intervals,
       
  6967     // the decision whether to send RS/NS or not, is tricky... -- msa
       
  6968     //
       
  6969     // The process starts when interface does the UP transition (see StartSending),
       
  6970     // at that point the start time of the process is saved into iAddress.iCreated
       
  6971     //
       
  6972     // If (transmitted_packets * transmit_interval <= elapsed)
       
  6973     //     a packet can be sent;
       
  6974     //
       
  6975     // Timeout can be called more often than packets are sent, but only after sufficient
       
  6976     // amount of time has passed, the actual sending occurs. [If there is a configuration
       
  6977     // error, and either transmit_interval is ZERO, then those packets are sent back to
       
  6978     // back without delay (causing *recursive* calls to this Timeout()!)].
       
  6979     //
       
  6980 #ifdef SYMBIAN_TCPIPDHCP_UPDATE  
       
  6981     #ifdef _DEBUG
       
  6982         LOG(Log::Printf(_L("<>\tCIp6Interface::Timeout()")));
       
  6983     #endif
       
  6984 #endif // SYMBIAN_TCPIPDHCP_UPDATE  
       
  6985     TUint next_event = KMaxTUint;
       
  6986     //
       
  6987     // Go through all Address blocks
       
  6988     //
       
  6989     TIp6AddressInfo *privacy = NULL;
       
  6990     TInt have_address = 0;
       
  6991     for (TIp6AddressInfo *id = &iAddress;;)
       
  6992         {
       
  6993         if (id->IsSet())
       
  6994             {
       
  6995             TUint elapsed_units = ElapsedUnits(id->iCreated, aStamp);
       
  6996 #ifdef _LOG
       
  6997             TLogAddressPrefix tmp(id->iId, id->iPrefix == 0 ? 128 : id->iPrefix);
       
  6998             Log::Printf(_L("\tIF %u [%S] ADDRESS %S %S%S age=%u [1/%d s] PLT=%u VLT=%u"),
       
  6999                 iScope[0], &iName, &tmp, &id->LogAddressType(), &id->LogAddressState(), elapsed_units, TIMER_UNIT, id->iPLT, id->iVLT);
       
  7000 #endif
       
  7001             // Some timers and values are different for IPv4 link local
       
  7002             const TInt is_ip4_local = id->iId.IsV4Mapped() && id->iId.Scope() == KIp6AddrScopeLinkLocal;
       
  7003             const TUint retrans_timer = is_ip4_local ? CIp6Manager::TimerUnits(iND.iIPv4RetransTimer) : iRetransTimer;
       
  7004             const TUint dup_transmits = is_ip4_local ? iND.iIPv4DupAddrDetectTransmits : iND.iDupAddrDetectTransmits;
       
  7005             have_address = 1; // ..although, it may be tentative!
       
  7006             if (aStamp < id->iCreated)
       
  7007                 {
       
  7008                 // Can only happen when iCRT is set to future (may happen with delay > 0 setting)
       
  7009                 const TUint time = ElapsedUnits(aStamp, id->iCreated);
       
  7010                 if (next_event > time)
       
  7011                     next_event = time;
       
  7012                 }
       
  7013             else
       
  7014                 {
       
  7015                 //
       
  7016                 // goto's used, sorry. It's just simpler this way (without replicating code)
       
  7017                 //
       
  7018                 TUint time = id->iNS * retrans_timer;
       
  7019                 if (id->IsTentative())
       
  7020                     {
       
  7021                     if (id->iNS == 0)
       
  7022                         {
       
  7023                         // This branch is to "fix" sluggish RunL() calls. When a timeout is scheduled
       
  7024                         // the call to RunL gets sometimes delayed and CRT < Current Time. If this is
       
  7025                         // the first DAD NS, adjust CRT to the current real time.
       
  7026                         id->iCreated = aStamp;
       
  7027                         elapsed_units = 0;
       
  7028                         }
       
  7029                     //
       
  7030                     // Duplicate Address Detection
       
  7031                     //
       
  7032                     // Time to send another NS?
       
  7033                     if (time <= elapsed_units)
       
  7034                         {
       
  7035                         if (id->iNS < dup_transmits)
       
  7036                             {
       
  7037                             id->iNS++;
       
  7038                             LOG(Log::Printf(_L("\tIF %u [%S] Sending %d. NS for %S"), iScope[0], &iName, id->iNS, &tmp));
       
  7039                             // note: source address is forced to be NONE!
       
  7040                             (void)SendNeighbors(KInet6ICMP_NeighborSol, NULL, id->iId, &KInet6AddrNone);
       
  7041                             time = retrans_timer;   // schedule next event at retrans timer
       
  7042                             }
       
  7043                         else
       
  7044                             {
       
  7045                             id->SetInitial(0);      // Done!
       
  7046                             
       
  7047                             // Generate an event indicating DAD is complete (iState has changed)
       
  7048                             NotifyAddressEvent(EventTypeModify, id->iId, id->iPrefix, NULL, *id);
       
  7049                             
       
  7050                             // Because missing source address punts flows to holding,
       
  7051                             // need to do the ScanHoldings, instead of notifying just
       
  7052                             // flows on current interface... -- msa (see RefreshFlow)
       
  7053                             Interfacer().ScanHoldings();
       
  7054                             goto announce_test; // Address ready, do the announce test!
       
  7055                             }
       
  7056                         }
       
  7057                     else
       
  7058                         time -= elapsed_units;  // compute the remaining wait time.
       
  7059                     if (next_event > time)
       
  7060                         next_event = time;
       
  7061                     goto expiration_test;// Address not ready yet, skip over announcement test!
       
  7062                     }
       
  7063 
       
  7064 announce_test:  // Need to send IPv4 (link local) announcements?
       
  7065                 if (is_ip4_local && NeedsND())
       
  7066                     {
       
  7067                     //
       
  7068                     // For IPv4 link local addresses, send 2 extra "announcements" after address has been accepted
       
  7069                     //
       
  7070                     if (id->iNS < dup_transmits + iND.iIPv4DupAddrAnnouncements)
       
  7071                         {
       
  7072                         // Time to send another announcement?
       
  7073                         if (time <= elapsed_units)
       
  7074                             {
       
  7075                             id->iNS++;
       
  7076                             LOG(Log::Printf(_L("\tIF %u [%S] Sending %d. NS (announce) for %S"), iScope[0], &iName, id->iNS, &tmp));
       
  7077                             (void)SendNeighbors(KInet6ICMP_NeighborSol, NULL, id->iId, &id->iId);
       
  7078                             time = retrans_timer;
       
  7079                             }
       
  7080                         else
       
  7081                             time -= elapsed_units;
       
  7082                         if (next_event > time)
       
  7083                             next_event = time;
       
  7084                         }
       
  7085                     }
       
  7086 
       
  7087                 // Just remember one id/address block for which lifetime processing
       
  7088                 // is required (don't want to it inside the loop, because it may
       
  7089                 // require removal and/or addition of new entries, and the loop would
       
  7090                 // need to be more complex... -- msa)
       
  7091 expiration_test:
       
  7092                 if (id->iPLT < elapsed_units)
       
  7093                     privacy = id;
       
  7094                 else if (id->iPLT != KLifetimeForever)
       
  7095                     {
       
  7096                     const TUint time = id->iPLT - elapsed_units;
       
  7097                     if (time < next_event)
       
  7098                         next_event = time;
       
  7099                     }
       
  7100 
       
  7101                 if (id->iVLT <= elapsed_units)
       
  7102                     privacy = id;
       
  7103                 else if (id->iVLT != KLifetimeForever)
       
  7104                     {
       
  7105                     const TUint time = id->iVLT - elapsed_units;
       
  7106                     if (time < next_event)
       
  7107                         next_event = time;
       
  7108                     }
       
  7109                 }
       
  7110             }
       
  7111         if (id->iNext == NULL)
       
  7112             break;
       
  7113         id = &id->iNext->iInfo;
       
  7114         }
       
  7115     if (privacy)
       
  7116         {
       
  7117         const TLifetime current_age = ElapsedUnits(privacy->iCreated, aStamp);
       
  7118         // At most one entry handled at each Timeout(). As these lifetimes should be
       
  7119         // relatively long, anything missed on current pass, will get handled on the
       
  7120         // next round!
       
  7121         if (privacy->iPLT < current_age)
       
  7122             {
       
  7123             // If RFC-3041 is being supported and this is randomly generated id
       
  7124             // for that purpose, one should at least now (but preferrably already
       
  7125             // earlier) regenerate a new random id! This id may still have valid
       
  7126             // life left, so it continues to be used with old connections...
       
  7127             if (privacy->iPrefix == 0)
       
  7128                 {
       
  7129                 SetPrefix(privacy->iId, 128, 1, KLifetimeForever, 0);
       
  7130                 }
       
  7131             }
       
  7132         if (privacy->iVLT < current_age)
       
  7133             RemId(privacy);
       
  7134         }
       
  7135     // Should only be sending RS, if interface as at least one address
       
  7136     // (there is no point in sending RS, if all addresses have become
       
  7137     // disabled by DAD). Also, needs to be IPv6 enabled interface.
       
  7138     // [Even if there are routers, must at least send one RS and get
       
  7139     // one reply after such RS]
       
  7140     if (have_address && CanSendRS())
       
  7141         {
       
  7142         //
       
  7143         // Try to find if routers are available
       
  7144         //
       
  7145         if (iRetryRS < iND.iMaxRouterSolicitations)
       
  7146             {
       
  7147             const TUint interval = CIp6Manager::TimerUnits(iND.iRtrSolicitationInterval);
       
  7148             // The router discovery "borrows" the creation time of the
       
  7149             // primary address...
       
  7150             TUint time = iRetryRS * interval;
       
  7151             if (iAddress.iCreated > aStamp)
       
  7152                 {
       
  7153                 // Creation time in future, need to wait...
       
  7154                 time = ElapsedUnits(aStamp, iAddress.iCreated);
       
  7155                 }
       
  7156             else
       
  7157                 {
       
  7158                 const TUint elapsed = ElapsedUnits(iAddress.iCreated, aStamp);
       
  7159                 if (time <= elapsed)
       
  7160                     {
       
  7161                     iRetryRS++;
       
  7162                     LOG(Log::Printf(_L("\tIF %u [%S] Sending %d. RS"), iScope[0], &iName, iRetryRS));
       
  7163                     // note: src address is not specified: it can be either none or some valid address
       
  7164                     // of the interface!
       
  7165                     (void)SendNeighbors(KInet6ICMP_RouterSol, NULL, KInet6AddrNone);
       
  7166                     time = interval;
       
  7167                     }
       
  7168                 else
       
  7169                     time -= elapsed;
       
  7170                 }
       
  7171             if (next_event > time)
       
  7172                 next_event = time;
       
  7173             }
       
  7174         }
       
  7175     if (NeedsND())
       
  7176         {
       
  7177         // An experimental code for cleaning out excess
       
  7178         // unused neighbor cache entries: pick the one
       
  7179         // with oldest reachable confirmation and if
       
  7180         // the time elapsed is long enough, delete it.
       
  7181         //
       
  7182         // *NOTE* During DAD/RS process, this code is
       
  7183         // executed for each timeout (probably wasted
       
  7184         // effort), but DAD/RS procesess are only active
       
  7185         // for short period of time, so it *should* not
       
  7186         // matter... -- msa
       
  7187         const TUint current = User::TickCount();
       
  7188         TUint oldest_time = 0;
       
  7189         CIp6Route *oldest_rt = NULL;
       
  7190         LOG(Log::Printf(_L("\tIF %u [%S] Neighbor cache cleanup check"), iScope[0], &iName));
       
  7191         for (CIp6Route *rt = iRouteList; rt != NULL; rt = rt->iNext)
       
  7192             {
       
  7193             if (rt->IsHostRoute() &&
       
  7194                 rt->iIsRouter == 0 &&       // ..do not expire routers...
       
  7195                 rt->iFlowList == NULL &&    // ..only, if no flows!
       
  7196                 // ..below test should work correctly even if TickCount
       
  7197                 // wraps around! [without the wraparound "problem", could
       
  7198                 // just look for the smallest timestamp... -- msa]
       
  7199                 oldest_time < (TUint)(current - rt->iTimeStamp))
       
  7200                 {
       
  7201                 oldest_time = current - rt->iTimeStamp;
       
  7202                 oldest_rt = rt;
       
  7203                 }
       
  7204             }
       
  7205         // "long enough" = ~8*iReachableTime
       
  7206         if (oldest_time / 8 > iReachableTime)
       
  7207             // no need to test oldest_rt != NULL! if oldest_time is
       
  7208             // is non-zero, then also oldest_rt != NULL. -- msa
       
  7209             RemoveRoute(oldest_rt);
       
  7210         //
       
  7211         // Just use the *default* reachable time as a basis for
       
  7212         // repeating this loop [given in milliseconds, needs to
       
  7213         // be converted into units]
       
  7214         //
       
  7215         // *NOTE* This means that a timer is always active for
       
  7216         // ND interface entries... -- msa
       
  7217         const TUint schedule = CIp6Manager::TimerUnits(KInetNdConfig.iReachableTime, 1000);
       
  7218         if (next_event > schedule)
       
  7219             next_event = schedule;
       
  7220         }
       
  7221     
       
  7222 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
  7223     // RFC 5006 Changes
       
  7224     // Since CIP6Interface::Timeout()handles RS initiation every 30 seconds, not necessary for 5006 to do it again
       
  7225     // Synchronise RDNSS server list and Repository for every 30 seconds 
       
  7226        if(iRdnssList!= NULL)           
       
  7227             {
       
  7228 #ifdef _DEBUG
       
  7229             LOG(Log::Printf(_L("\tIF %u [%S] RDNSS Cache Cleanup"), iScope[0], &iName));
       
  7230 #endif          
       
  7231             if (iRdnssList->RdnssServerListSync(iNameSer1, iNameSer2))
       
  7232                 {
       
  7233                 (void)SendNeighbors(KInet6ICMP_RouterSol, NULL, KInet6AddrNone);
       
  7234                 LOG(Log::Printf(_L("\tIF %u [%S]RDNSS: Sending RS"), iScope[0], &iName));
       
  7235                 }
       
  7236             
       
  7237             // Update Nameserver repository only if iRdnssFlag was reset to zero
       
  7238             // Even if either iNameSer1 or iNameSer2 is elapsed iRdnssFlag was reset to zero
       
  7239             // Need to update both iNameSer1/iNameSer2 with KAFUnspec or a valid DNS address from iRdnssArrayList 
       
  7240             if( (((iRdnssList->GetRdnssFlag())& RDNSS_NAMESERVER1) ==0) || 
       
  7241                 (((iRdnssList->GetRdnssFlag())& RDNSS_NAMESERVER2)== 0) 
       
  7242                 )
       
  7243                 {
       
  7244                 iRdnssList->RdnssNameServerUpdate(iNameSer1,(TUint8)0);
       
  7245                 iRdnssList->RdnssNameServerUpdate(iNameSer2,(TUint8)1);
       
  7246                 LOG(Log::Printf(_L("\tIF RDNSS TABLE After SYNC")));
       
  7247                 TInt arrayCount = iRdnssList->CountRdnssEntry();
       
  7248                 for(TUint8 index =0;index<arrayCount;index++)
       
  7249                     {   
       
  7250                      iRdnssList->PrintRdnssServerList(index);
       
  7251                     }
       
  7252                 }
       
  7253             if(iRdnssList->GetRdnssFlag()) //Notify only if changed
       
  7254              NotifyInterfaceEvent(EventTypeModify);     
       
  7255             }
       
  7256 #endif // SYMBIAN_TCPIPDHCP_UPDATE
       
  7257        
       
  7258     if (next_event < KMaxTUint)
       
  7259         {
       
  7260         LOG(Log::Printf(_L("\tIF %u [%S] Schedule next timeout after %u/%u s"),
       
  7261             iScope[0], &iName, next_event, TIMER_UNIT));
       
  7262         Interfacer().SetTimerWithUnits(iTimeout, next_event);
       
  7263         }
       
  7264     else
       
  7265         {
       
  7266         LOG(Log::Printf(_L("\tIF %u [%S] Sleeps, no timeout"), iScope[0], &iName));
       
  7267         CancelTimer();
       
  7268         }
       
  7269     }
       
  7270 
       
  7271 CIp6Interface::~CIp6Interface()
       
  7272     {
       
  7273     // Note: Reset does some extra inits, which
       
  7274     // are wasted on destructor. Should not cause
       
  7275     // any problems... -- msa
       
  7276     Reset();
       
  7277     LOG(Log::Printf(_L("\tIF %u [%S] Deleted"), iScope[0], &iName));
       
  7278     }
       
  7279 
       
  7280 // CIp6Interface::Reset
       
  7281 // ********************
       
  7282 /**
       
  7283 // Release all attached resources and set the instance into
       
  7284 // initial state. Can be called any time.
       
  7285 //
       
  7286 // EXCEPTION: DO NOT TOUCH 'iNetDial' in Reset!
       
  7287 //
       
  7288 // NOTE: Also used from the class destructor!
       
  7289 */
       
  7290 void CIp6Interface::Reset(TInt aKeepNif)
       
  7291     {
       
  7292     LOG(Log::Printf(_L("\tIF %u [%S] Reset(%d)"), iScope[0], &iName, aKeepNif));
       
  7293     CancelTimer();  // Prevent any timers fromm firing
       
  7294     //
       
  7295     // Empty the hold queue
       
  7296     //
       
  7297     iHoldQueue.Free();
       
  7298     //
       
  7299     // Remove all routes
       
  7300     //
       
  7301     CIp6Route *rh = iRouteList;
       
  7302     iRouteList = NULL;
       
  7303     iRouters = 0;   // No routers left either!
       
  7304     while (rh != NULL)
       
  7305         {
       
  7306         CIp6Route *const r = rh;
       
  7307         rh = r->iNext;
       
  7308         // Because ALL entries are going to be deleted, there
       
  7309         // is no need to worry about iRouter pointers.
       
  7310         NotifyRouteEvent(EventTypeDelete, r);
       
  7311         delete r;
       
  7312         }
       
  7313     ASSERT(iFlows == 0);
       
  7314     //
       
  7315     iIsIPv6 = 0;
       
  7316     iIsIPv4 = 0;
       
  7317     iIsRouter = 0;
       
  7318     iIsSuspended = 0;
       
  7319     iIpv4Linklocal = EV4LLUnknown;
       
  7320     //
       
  7321     // Remove address information
       
  7322     //
       
  7323     TIp6AddressInfo ai = iAddress;
       
  7324     iAddress.iNext = NULL;
       
  7325     iAddress.iId = KInet6AddrNone;
       
  7326     iAddress.SetNoAddress();
       
  7327     iAddress.iIpv4LinkLocal = 0;
       
  7328     for (;;)
       
  7329         {
       
  7330         if (ai.IsSet())
       
  7331             NotifyAddressEvent(EventTypeDelete, ai.iId, ai.iPrefix, NULL, ai);
       
  7332         CIp6Address *const a = ai.iNext;
       
  7333         if (a == NULL)
       
  7334             break;
       
  7335         ai = a->iInfo;
       
  7336         delete a;
       
  7337         }
       
  7338 
       
  7339     // Reset the scope vector: fill all scope levels
       
  7340     // with unique non-zero id by loading a complement
       
  7341     // of the interface index into them.
       
  7342     for (TInt i = 1; i <= EScopeType_NET; ++i)
       
  7343         iScope[i] = ~iScope[0];
       
  7344 
       
  7345     iTimeStamp.UniversalTime(); // A new "birthday" for the interface
       
  7346     iState = KErrNone;  // is this needed?? -- msa
       
  7347 
       
  7348     // Reset some other address fields
       
  7349     iHwAddr.SetFamily(0);
       
  7350     iNameSer1.Init(0);
       
  7351     iNameSer2.Init(0);
       
  7352 
       
  7353 
       
  7354     iSMtu = 0;
       
  7355     iRMtu = 0;
       
  7356     iPMtu = 0;
       
  7357 
       
  7358     // Reset default hoplimit from the configured default
       
  7359     iHopLimit = Interfacer().iMaxTTL;
       
  7360     //
       
  7361     // Reset ND parameters (whether needed or not)
       
  7362     //
       
  7363     iND = KInetNdConfig;
       
  7364     SetReachableTime(); // Initial value
       
  7365     SetRetransTimer();  // Initial value
       
  7366     //
       
  7367     // Remove NIFMAN/Interface associations
       
  7368     //
       
  7369     if (aKeepNif == 0 && iNifIf)
       
  7370         {
       
  7371         // ...notify network layer, in case any hook is interested.
       
  7372         // Use temporary safe "nif" variable, because there could
       
  7373         // some callbacks from the hooks within the InterfaceDetached
       
  7374         // method(s).
       
  7375         CNifIfBase *const nif = iNifIf;
       
  7376         iNifIf = NULL;
       
  7377         if (iNifUser->iNetwork)
       
  7378             iNifUser->iNetwork->InterfaceDetached(iName, nif);
       
  7379         nif->Close();
       
  7380         }
       
  7381 #ifdef SYMBIAN_TCPIPDHCP_UPDATE		
       
  7382     //RFC-5006 Changes for RDNSS option
       
  7383     delete iRdnssList;
       
  7384     iRdnssList = NULL;
       
  7385 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
  7386     }
       
  7387 
       
  7388 
       
  7389 TInt CIp6Interface::HaveIp4LinkLocal()
       
  7390     /**
       
  7391     * Tells whether IPv4 link-local addresses are in use.
       
  7392     * The possible return values are enumerated in EV4LLEnums.
       
  7393     */
       
  7394     {
       
  7395     // - If the IPv4 Link-local parameter was already set for this interface, use that
       
  7396     // - If it was not set, apply the following search order when looking for ipv4linklocal
       
  7397     //   1. [interface name] - specific section in tcpip6.ini
       
  7398     //   2. [ip] - section in tcpip6.ini
       
  7399     if (iIpv4Linklocal != EV4LLUnknown)
       
  7400         return iIpv4Linklocal;
       
  7401         
       
  7402     TInt value = 0;
       
  7403     if (!Interfacer().FindVar(iName, TCPIP_INI_IPV4LINKLOCAL, value))
       
  7404         iIpv4Linklocal = Interfacer().iIpv4Linklocal;
       
  7405     else if (value < 0 || value > 3)
       
  7406         iIpv4Linklocal = Interfacer().iIpv4Linklocal;
       
  7407     else
       
  7408         iIpv4Linklocal = value;
       
  7409         
       
  7410     return iIpv4Linklocal;
       
  7411     }
       
  7412 
       
  7413 
       
  7414 //
       
  7415 // **************************
       
  7416 // CIp6Manager Implementation
       
  7417 // **************************
       
  7418 //
       
  7419 //
       
  7420 CIp6Manager::CIp6Manager() : iTimeout(CIp6ManagerTimeoutLinkage::Timeout)
       
  7421     {
       
  7422     }
       
  7423 
       
  7424 CIfManager *CIfManager::NewL()
       
  7425     {
       
  7426     CIp6Manager *mgr = new (ELeave) CIp6Manager();
       
  7427     CleanupStack::PushL(mgr);
       
  7428     mgr->InitL();
       
  7429     CleanupStack::Pop();
       
  7430     return mgr;
       
  7431     };
       
  7432 
       
  7433 
       
  7434 TInt CIp6Manager::GetIniValue(const TDesC &aSection, const TDesC &aName, TInt aDefault, TInt aMin, TInt aMax)
       
  7435     /**
       
  7436     * Get tcpip.ini value.
       
  7437     *
       
  7438     * @param aSection The [section] name
       
  7439     * @param aName The variblae name
       
  7440     * @param aDefault The value returned, if variable is undefined, invalid or out of range.
       
  7441     * @param aMin The minimum allowed value
       
  7442     * @param aMax The maximum allowed value
       
  7443     *
       
  7444     * @return The either the aDefault, or value parsed from the ini file.
       
  7445     */
       
  7446     {
       
  7447     LOG(_LIT(KFormat, "\t[%S] %S = %d"));
       
  7448     LOG(_LIT(KFormatInv, "\t[%S] %S = %d is invalid"));
       
  7449 
       
  7450     TInt value;
       
  7451     if (!FindVar(aSection, aName, value))
       
  7452         value = aDefault;
       
  7453     else if (value < aMin || value > aMax)
       
  7454         {
       
  7455         LOG(Log::Printf(KFormatInv, &aSection, &aName, value));
       
  7456         value = aDefault;
       
  7457         }
       
  7458     LOG(Log::Printf(KFormat, &aSection, &aName, value));
       
  7459     return value;
       
  7460     }
       
  7461 
       
  7462 void CIp6Manager::InitL()
       
  7463     {
       
  7464     LOG(Log::Printf(_L("--- tcpip6 starting, version: [%S] ---"), &KInet6Version));
       
  7465 
       
  7466     // Create EventManager instance. May return NULL.
       
  7467     iEventManager = MEventService::CreateEventManager(KNumClassesTcpIp6);
       
  7468     
       
  7469         {
       
  7470         // ini parameter value determines the destination cache granularity
       
  7471         // [ separate cache entry either 1=per address or 2=per prefix ]
       
  7472         const TInt keymode = GetIniValue(TCPIP_INI_IP, TCPIP_INI_DSTCACHE, 0, 0, 2);
       
  7473         if (keymode)
       
  7474             {
       
  7475             // Create Destination Cache instance. May return NULL
       
  7476             iDestinationCache = MDestinationCache::CreateDstCache(keymode);
       
  7477             if (iDestinationCache)
       
  7478                 {
       
  7479                 iDestinationCache->SetLifetime(GetIniValue(TCPIP_INI_IP, TCPIP_INI_DST_LIFETIME, KDstCacheLifetime, 1, KMaxTInt));
       
  7480                 iDestinationCache->SetMaxSize(GetIniValue(TCPIP_INI_IP, TCPIP_INI_DST_MAXSIZE, KDstCacheMaxSize, 0, KMaxTInt));
       
  7481                 }
       
  7482             }
       
  7483         }
       
  7484     //
       
  7485     // Create the NIF "proxies" for the protocols
       
  7486     //
       
  7487     for (TInt i = 0; i < (TInt)(sizeof(iNifUser) / sizeof(iNifUser[0])); ++i)
       
  7488         iNifUser[i] = new (ELeave) CIp6NifUser(*this, i == E_IPv4);
       
  7489 
       
  7490     // Just put something non-zero into iSeed
       
  7491     // (should use something other than 'this', as it may leak unwanted
       
  7492     // information out. Also, not random enough, if multiple identical
       
  7493     // devices are on the same net booting at same time -- fix sometime -- msa)
       
  7494     const TUint32 seed[2] = {(TUint32)this, ~(TUint32)this};
       
  7495     iSeed = *(const TInt64*)&seed;
       
  7496     //
       
  7497     // Compute maximum interval in seconds, that can be expressed in ticks difference
       
  7498     //
       
  7499     TReal interval = (TReal)KMaxTInt * TickPeriod() / 1000000.0;
       
  7500     (void)Math::Int((TInt32 &)iMaxTickInterval, interval);
       
  7501     LOG(Log::Printf(_L("\tMaxTickInterval = %d\n"), (int)iMaxTickInterval));
       
  7502 
       
  7503     //
       
  7504     // Create Timer Service
       
  7505     //
       
  7506     iTimeoutManager = TimeoutFactory::NewL(TIMER_UNIT, this, KTcpipIni_TimeoutPriority);
       
  7507     //
       
  7508     // Create a special holding route.
       
  7509     // Load the route with 128 prefix and no address (= illegal destination)
       
  7510     // => Thus, holding route is never selected by plain FindRoute! -- msa
       
  7511     AddRouteL(KInet6AddrNone, 128, _L(""));
       
  7512     //
       
  7513     // At this stage, the above route should be the *ONLY* one existing
       
  7514     // iHoldingRoute is just a copy pointer to special route entry.
       
  7515     // DO not use delete on it!
       
  7516     //
       
  7517     iHoldingRoute = iInterfaceList->iRouteList;
       
  7518     if (iHoldingRoute == NULL)
       
  7519         // In this case AddRouteL returns and fails to
       
  7520         // create first entry to the iRouteList only if
       
  7521         // route allocation fails due to heap. There is
       
  7522         // no point in going on with stack initialize,
       
  7523         // just leave (and and shutdown).
       
  7524         User::Leave(KErrNoMemory);
       
  7525 
       
  7526     ASSERT(iHoldingRoute->iNext == NULL);
       
  7527     iHoldingRoute->iState = CIp6Route::EHolding;
       
  7528 
       
  7529     //
       
  7530     // Default TTL/HopLimit
       
  7531     //
       
  7532     iMaxTTL = (TUint8)GetIniValue(TCPIP_INI_IP, TCPIP_INI_MAXTTL, KTcpipIni_Maxttl, 0, 255);
       
  7533     //
       
  7534     // Default TTL/HopLimit for link local unicast targets
       
  7535     // (if value is negative, the default is same as for normal unicast)
       
  7536     //
       
  7537     iLinkLocalTTL = GetIniValue(TCPIP_INI_IP, TCPIP_INI_LINKLOCALTTL, KTcpipIni_LinkLocalttl, -1, 255);
       
  7538 
       
  7539     // Set default how interface errors should affect the flows
       
  7540     // (If flag is 1, then interface error just moves the flow to pending
       
  7541     // state and waits for the same or some other interface to become
       
  7542     // available again..)
       
  7543     iNoInterfaceError = (GetIniValue(TCPIP_INI_IP, TCPIP_INI_NOIFERROR, KTcpipIni_Noiferror) != 0);
       
  7544 
       
  7545     // Set default whether a flow should be counted on the interface
       
  7546     // or not. When counted, positive count on interface will cause
       
  7547     // the NIF OpenRoute() called, and when count reaches ZERO, the
       
  7548     // CloseRoute() is called.
       
  7549     iKeepInterfaceUp = (GetIniValue(TCPIP_INI_IP, TCPIP_INI_KEEP_INTERFACE_UP, KTcpipIni_KeepInterfaceUp) != 0);
       
  7550 
       
  7551     // iMaxHoldingTime sets the approximate time limit for a flow to be waiting
       
  7552     // for a route or netdial completion in pending state.
       
  7553     // A value 0 can be used to disable expiration of the hold (= "infinite" time)
       
  7554     iMaxHoldingTime = (TUint)GetIniValue(TCPIP_INI_IP, TCPIP_INI_MAXHOLDTIME, KTcpipIni_Maxholdtime, 0, iMaxTickInterval);
       
  7555 
       
  7556     // iShutdownDelay defines the time to wait before daemons are killed
       
  7557     // after last user leaves the stack.
       
  7558     iShutdownDelay = GetIniValue(TCPIP_INI_IP, TCPIP_INI_SHUTDOWN_DELAY, KTcpipIni_ShutdownDelay, 0, KMaxTInt);
       
  7559 
       
  7560     // iIpv4Linklocal enables automatic IPv4 link local addresses from
       
  7561     // 169.254.0.0/16
       
  7562     iIpv4Linklocal = GetIniValue(TCPIP_INI_IP, TCPIP_INI_IPV4LINKLOCAL, KTcpipIni_Ipv4Linklocal, 0, 3);
       
  7563         
       
  7564     // Allow disabling a part of "DIID" (if set, do not defend my
       
  7565     // interface ID's aggressively.
       
  7566     iNoDefendId = (GetIniValue(TCPIP_INI_IP, TCPIP_INI_NODEFENDID, KTcpipIni_NoDefendId) != 0);
       
  7567 
       
  7568     // Control ND probing. If enabled, stack probes for the destination
       
  7569     // address on all interfaces in the scope, when destination does not
       
  7570     // have a route (e.g. if system has no default route).  This setting
       
  7571     // is ignored if disabled if the source address is an IPv4 link local
       
  7572     // or else the link local would not function except for neighbours
       
  7573     // with routes already discovered and cached.  This is necessary for
       
  7574     // compliance with the ZEROCONF RFC.
       
  7575     iProbeAddress = (GetIniValue(TCPIP_INI_IP, TCPIP_INI_PROBEADDRESS, KTcpipIni_ProbeAddress) != 0);
       
  7576 
       
  7577     // Control support of the Route Information option. The option is enabled, if the value
       
  7578     // is non-zero. The value defines the option type to be used.
       
  7579     iRA_OptRoute = (TUint8)GetIniValue(TCPIP_INI_IP, TCPIP_INI_RA_OPT_ROUTE, 0, 0, 255);
       
  7580     
       
  7581 #ifndef SYMBIAN_TCPIPDHCP_UPDATE 
       
  7582     // Control support of the RDNSS option. The option is enabled, if the value
       
  7583     // is non-zero. The value defines the option type to be used.
       
  7584     iRA_OptDns = (TUint8)GetIniValue(TCPIP_INI_IP, TCPIP_INI_RA_OPT_RDNSS, 0, 0, 255);
       
  7585 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
  7586     }
       
  7587 
       
  7588 TBool CIp6Manager::LoadConfigurationFile()
       
  7589     {
       
  7590     if (iConfig)
       
  7591         return TRUE;    // Already loaded!
       
  7592     // if iConfigErr != 0 (KErrNone), then an attempt for
       
  7593     // loading configuration has been made and failed,
       
  7594     // assume it never will succeed and avoid further
       
  7595     // attemps on each FindVar...
       
  7596     if (iConfigErr)
       
  7597         return FALSE;
       
  7598     LOG(Log::Printf(_L("CIp6Manager::LoadConfigurationFile(): %S"), &TCPIP_INI_DATA));
       
  7599     TRAP(iConfigErr, iConfig = CESockIniData::NewL(TCPIP_INI_DATA));
       
  7600     return (iConfig != NULL);
       
  7601     }
       
  7602 
       
  7603 //
       
  7604 // Access to the configuration file (tcpip.ini)
       
  7605 //
       
  7606 TBool CIp6Manager::FindVar(const TDesC &aSection, const TDesC &aVarName, TPtrC &aResult)
       
  7607     {
       
  7608     if (LoadConfigurationFile())
       
  7609         {
       
  7610         ASSERT(iConfig);    // <-- lint gag
       
  7611         return iConfig->FindVar(aSection, aVarName, aResult);
       
  7612         }
       
  7613     return FALSE;
       
  7614     }
       
  7615 
       
  7616 TBool CIp6Manager::FindVar(const TDesC &aSection, const TDesC &aVarName, TInt &aResult)
       
  7617     {
       
  7618     if (LoadConfigurationFile())
       
  7619         {
       
  7620         ASSERT(iConfig);    // <-- lint gag
       
  7621         return iConfig->FindVar(aSection, aVarName, aResult);
       
  7622         }
       
  7623     return FALSE;
       
  7624     }
       
  7625 
       
  7626 CIp6Manager::~CIp6Manager()
       
  7627     {
       
  7628     LOG(Log::Printf(_L("~CIp6Manager()")));
       
  7629 
       
  7630     CancelTimer();
       
  7631 
       
  7632     StopDaemons();
       
  7633 
       
  7634     // Release all interfaces
       
  7635 
       
  7636     while (iInterfaceList)
       
  7637         {
       
  7638         CIp6Interface *iface = iInterfaceList;
       
  7639         iInterfaceList = iface->iNext;
       
  7640         delete iface;
       
  7641         }
       
  7642     delete iTimeoutManager;
       
  7643     delete iConfig;
       
  7644     //
       
  7645     // Destroy NIF "proxies"
       
  7646     //
       
  7647     for (TInt i = 0; i < (TInt)(sizeof(iNifUser) / sizeof(iNifUser[0])); ++i)
       
  7648         delete iNifUser[i];
       
  7649 
       
  7650     ASSERT(iFlows == 0);
       
  7651 
       
  7652     delete iEventManager;
       
  7653     delete iDestinationCache;
       
  7654     LOG(Log::Printf(_L("--- tcpip6 finished, version: [%S] ---"), &KInet6Version));
       
  7655     }
       
  7656 
       
  7657 // *************************
       
  7658 // CIp6Manager::StartDaemons
       
  7659 // *************************
       
  7660 void CIp6Manager::StartDaemons()
       
  7661     {
       
  7662     ASSERT(iDaemons == NULL);
       
  7663     LOG(Log::Printf(_L("CIp6Manager::StartDaemons()")));
       
  7664 
       
  7665     //
       
  7666     // Create and start Daemons (as specified in TCPIP.INI)
       
  7667     //
       
  7668     TPtrC daemons;
       
  7669     if (FindVar(TCPIP_INI_START, TCPIP_INI_DAEMONS, daemons))
       
  7670         {
       
  7671         TLex start(daemons);
       
  7672         while (!start.Eos())
       
  7673             {
       
  7674             start.Mark();
       
  7675             while (!start.Eos() && start.Peek() != ',')
       
  7676                 start.Inc();
       
  7677 
       
  7678             TPtrC demon = start.MarkedToken();
       
  7679             if (!start.Eos())
       
  7680                 start.Inc();    // Skip ','
       
  7681             TPtrC name;
       
  7682             if (FindVar(demon, TCPIP_INI_FILENAME, name))
       
  7683                 {
       
  7684                 CIp6Daemon *d = new CIp6Daemon;
       
  7685                 if (!d)
       
  7686                     return; // should probably tell someone about this fail!
       
  7687                 d->iNext = iDaemons;
       
  7688                 iDaemons = d;
       
  7689                 d->Start(demon, name);
       
  7690                 }
       
  7691             else
       
  7692                 {
       
  7693                 // Should probably report this. It's an TCPIP.INI error
       
  7694                 // to reference a daemon section that does not exist!
       
  7695                 LOG(Log::Printf(_L("CIp6Manager::InitL() '[%S] filename' not found\n"), &demon));
       
  7696                 }
       
  7697             }
       
  7698         }
       
  7699     }
       
  7700 
       
  7701 void CIp6Manager::StopDaemons()
       
  7702     {
       
  7703     LOG(Log::Printf(_L("CIp6Manager::StopDaemons()")));
       
  7704     // Kill active daemons
       
  7705     //
       
  7706     while (iDaemons)
       
  7707         {
       
  7708         CIp6Daemon *const d = iDaemons;
       
  7709         iDaemons = iDaemons->iNext;
       
  7710         delete d;
       
  7711         }
       
  7712     }
       
  7713 
       
  7714 // CIp6Manager::Timeout
       
  7715 // ********************
       
  7716 /**
       
  7717 // The manager Timeout is currently used only for "sluggish
       
  7718 // shutdown", so implentation is very simple...
       
  7719 */
       
  7720 void CIp6Manager::Timeout(const TTime & /*aStamp*/)
       
  7721     {
       
  7722     LOG(Log::Printf(_L("CIp6Manager::Timeout() iUsers=%d"), (int)iUsers));
       
  7723     if (iUsers == 0)
       
  7724         StopDaemons();
       
  7725     }
       
  7726 
       
  7727 
       
  7728 // CIp6Manager::TimerUnits
       
  7729 // ***********************
       
  7730 //
       
  7731 TUint CIp6Manager::TimerUnits(const TUint aDelay, const TUint aUnit)
       
  7732     /**
       
  7733     * Convert a delay time to internal timer units.
       
  7734     *
       
  7735     * If the converted result would exceed KMaxTUint, then
       
  7736     * KMaxTUint is returned.
       
  7737     *
       
  7738     * @param aDelay     The timer delay in specified units
       
  7739     * @param aUnit      The unit definition (fraction of second, [1..1000000])
       
  7740     * @return The delay in internal units [0..KMaxTUint].
       
  7741     */
       
  7742     {
       
  7743     if (aUnit == TIMER_UNIT)
       
  7744         return aDelay;
       
  7745 
       
  7746 #ifdef MAKE_TINT64
       
  7747     const TInt64 delay = (MAKE_TINT64(0U, TIMER_UNIT) * MAKE_TINT64(0U, aDelay) + MAKE_TINT64(0U, aUnit - 1)) / MAKE_TINT64(0U, aUnit);
       
  7748     return I64HIGH(delay) ? KMaxTUint : I64LOW(delay);
       
  7749 #else
       
  7750     const TInt64 delay((TInt64(0U, TIMER_UNIT) * TInt64(0U, aDelay) + TInt64(0U, aUnit - 1)) / TInt64(0U, aUnit));
       
  7751     return delay.High() ? KMaxTUint : delay.Low();
       
  7752 #endif
       
  7753     }
       
  7754 
       
  7755 
       
  7756 // CIp6Manager::SetTimerSeconds
       
  7757 // ****************************
       
  7758 void CIp6Manager::SetTimer(RTimeout &aHandle, TUint32 aDelay)
       
  7759     /**
       
  7760     * Set the timeout event on a handle.
       
  7761     *
       
  7762     * @param aHandle    The timeout handle
       
  7763     * @param aDelay     The timer delay in seconds
       
  7764     */
       
  7765     {
       
  7766 #if TIMER_UNIT == 1
       
  7767     // Timer unit is 1s, aDelay can be used as is.
       
  7768     iTimeoutManager->Set(aHandle, aDelay);
       
  7769 #else
       
  7770     // Timer unit not 1s, aDelay must be adjusted.
       
  7771     static const TUint KMaxDelay = KMaxTUint / TIMER_UNIT;
       
  7772     iTimeoutManager->Set(aHandle, aDelay > KMaxDelay ? KMaxTUint : aDelay * TIMER_UNIT);
       
  7773 #endif
       
  7774     }
       
  7775 
       
  7776 // CIp6Manager::IncUsers
       
  7777 // *********************
       
  7778 // Increment users
       
  7779 //
       
  7780 void CIp6Manager::IncUsers()
       
  7781     {
       
  7782     iUsers++;
       
  7783     LOG(Log::Printf(_L("\t\tIncUsers: Users=%d Nifs=%d"), iUsers, iNifCount));
       
  7784     if (iDaemons == NULL)
       
  7785         StartDaemons();
       
  7786     }
       
  7787 
       
  7788 // CIp6Manager::DecUsers
       
  7789 // *********************
       
  7790 // Decrement users count
       
  7791 //
       
  7792 void CIp6Manager::DecUsers()
       
  7793     {
       
  7794     __ASSERT_ALWAYS(iUsers > 0, User::Panic(_L("iUsers"), iUsers));
       
  7795     if (--iUsers == iNifCount)
       
  7796         {
       
  7797         // Only interfaces remain, no real clients
       
  7798         Nif::NetworkLayerClosed(*iNifUser[E_IPv6]);
       
  7799         Nif::NetworkLayerClosed(*iNifUser[E_IPv4]);
       
  7800         }
       
  7801     LOG(Log::Printf(_L("\t\tDecUsers: Users=%d Nifs=%d"), iUsers, iNifCount));
       
  7802     if (iUsers == 0)
       
  7803         {
       
  7804         //StopDaemons();
       
  7805         //
       
  7806         // Sometimes aggressive shutdown causes problems in system
       
  7807         // components. Use a small delay before really activating
       
  7808         // the daemon killer...
       
  7809         SetTimer(iShutdownDelay);
       
  7810         }
       
  7811     }
       
  7812 
       
  7813 // CIp6Manager::PacketAccepted
       
  7814 // ***************************
       
  7815 //
       
  7816 TInt CIp6Manager::PacketAccepted(const TUint32 aIndex)
       
  7817     {
       
  7818     const CIp6Interface *const iface = FindInterface(aIndex);
       
  7819     if (iface)
       
  7820         {
       
  7821         if (iface->iNifIf && iface->iNifIf->Notify())
       
  7822             return iface->iNifIf->Notify()->PacketActivity(EIncoming, 0, TRUE);
       
  7823         return KErrNone;
       
  7824         }
       
  7825     return KErrNotFound;
       
  7826     }
       
  7827 
       
  7828 //
       
  7829 // CIp6Manager::NewFlow
       
  7830 // ********************
       
  7831 // Create a new flow instance
       
  7832 //
       
  7833 CFlowContext *CIp6Manager::NewFlowL(const void *aOwner, MFlowManager *aManager, TUint aProtocol)
       
  7834     {
       
  7835     CFlowContext *flow = new (ELeave) CIp6Flow(aOwner, aManager, *this, aProtocol);
       
  7836     return flow;
       
  7837     }
       
  7838 
       
  7839 CFlowContext *CIp6Manager::NewFlowL(const void *aOwner, MFlowManager *aManager, CFlowContext &aFlow)
       
  7840     {
       
  7841     return new (ELeave) CIp6Flow(aOwner, aManager, *this, aFlow);
       
  7842     }
       
  7843 
       
  7844 
       
  7845 // CIp6Manager::Register
       
  7846 // *********************
       
  7847 // Attach a protocol to NIF "proxy"
       
  7848 MNifIfUser *CIp6Manager::Register(MNetworkServiceExtension *aNetwork)
       
  7849     {
       
  7850     TServerProtocolDesc info;
       
  7851     CIp6NifUser *ifuser = NULL;
       
  7852 
       
  7853     aNetwork->Protocol()->Identify(&info);
       
  7854     if (info.iAddrFamily == KAfInet6)
       
  7855         {
       
  7856         (ifuser = iNifUser[E_IPv6])->iNetwork = aNetwork;
       
  7857         }
       
  7858     else if (info.iAddrFamily == KAfInet)
       
  7859         {
       
  7860         (ifuser = iNifUser[E_IPv4])->iNetwork = aNetwork;
       
  7861         }
       
  7862     return ifuser;
       
  7863     }
       
  7864 
       
  7865 //
       
  7866 // CIp6Manager::Unregister
       
  7867 // ***********************
       
  7868 // Remove all references to the specified protocol
       
  7869 void CIp6Manager::Unregister(MNetworkServiceExtension *aNetwork)
       
  7870     {
       
  7871     for (TInt i = 0; i < (TInt)(sizeof(iNifUser) / sizeof(iNifUser[0])); ++i)
       
  7872         if (iNifUser[i]->iNetwork == aNetwork)
       
  7873             iNifUser[i]->iNetwork = NULL;
       
  7874     }
       
  7875 
       
  7876 // CIp6Manager::IcmpSend
       
  7877 // *********************
       
  7878 /**
       
  7879 // Wrap a packet into ICMP error reply and send it out.
       
  7880 //
       
  7881 // Delegate the task to the network instance MNetworkServiceExtension::IcmpWrap method.
       
  7882 //
       
  7883 // @param aPacket
       
  7884 //  The RMBuf chain containing the IP packet in packet state
       
  7885 // @param aIcmp
       
  7886 //  The 32 bit value containing type and code for both IPv4 and IPv6. The type and
       
  7887 //  code to be used are chosen based on the actual IP version of the packet.
       
  7888 // @param aParameter
       
  7889 //  The 32 bit value to be placed as the "parameter" field of the ICMP header.
       
  7890 // @param aMC
       
  7891 //  A flag, when non-Zero, forces sending of ICMP, even if the packet destination
       
  7892 //  was a multicast address (see MNetworkService::Icmp4Send and
       
  7893 //  MNetworkService::Icmp6Send).
       
  7894 */
       
  7895 void CIp6Manager::IcmpSend(RMBufChain &aPacket, const TIcmpTypeCode aIcmp, const TUint32 aParameter, const TInt aMC)
       
  7896     {
       
  7897     // Just use any "network" instance, and assume it works just
       
  7898     // as well whether IPv4 or IPv6...
       
  7899     MNetworkServiceExtension *const network = iNifUser[E_IPv6]->iNetwork ? iNifUser[E_IPv6]->iNetwork : iNifUser[E_IPv4]->iNetwork;
       
  7900     if (network)
       
  7901         network->IcmpWrap(aPacket, aIcmp, aParameter, aMC);
       
  7902     //
       
  7903     // Release packet (if not passed on)
       
  7904     //
       
  7905     aPacket.Free();
       
  7906     return;
       
  7907     }
       
  7908 
       
  7909 //
       
  7910 // CIp6Manager::IcmpError
       
  7911 // **********************
       
  7912 /**
       
  7913 // Gets a peek at all received ICMP error messages before they
       
  7914 // are passed to the upper layers. This is called from the
       
  7915 // IcmpError() method of the IP layer.
       
  7916 //
       
  7917 // @return
       
  7918 // @li < 0, if packet has been released (packet will not
       
  7919 //          go to the upper layer after this),
       
  7920 // @li = 0, the usual return, packet looked and it can be
       
  7921 //          passed to the upper layers
       
  7922 // @li > 0, *NOT USED NOW*, Treat as = 0 as default
       
  7923 */
       
  7924 TInt CIp6Manager::IcmpError(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo)
       
  7925     {
       
  7926     // note: iParameter is fixed by ICMP protocol as 32 bit entity.
       
  7927     // Assume that "natural" TUint will always be at least 32 bits
       
  7928     // (compiler should warn, if this is not true).
       
  7929     TUint mtu = aInfo.iParameter;
       
  7930     
       
  7931     //
       
  7932     // Currently the only interesting thing here is to detect the
       
  7933     // MTU affecting ICMP's for both IPv6 and IPv4.
       
  7934     //
       
  7935     if (aInfo.iIcmp == KProtocolInet6Icmp)
       
  7936         {
       
  7937         // IPv6 ICMP Errors
       
  7938         //
       
  7939         // The only insteresting error is KInet6ICMP_PacketTooBig,
       
  7940         //
       
  7941         if (aInfo.iType != KInet6ICMP_PacketTooBig)
       
  7942             return 0;
       
  7943         if (mtu < STATIC_CAST(TUint,KInet6MinMtu))
       
  7944             return 0;       // Cannot set it smaller than minimum MTU!
       
  7945         }
       
  7946     else if (aInfo.iIcmp == KProtocolInetIcmp)
       
  7947         {
       
  7948         // IPv4 ICMP Errors
       
  7949         //
       
  7950         if (aInfo.iType == KInet4ICMP_Redirect)
       
  7951             {
       
  7952             CIp6Interface *const ifp = FindInterface(aInfo.iInterfaceIndex);
       
  7953             if (ifp)
       
  7954                 ifp->Ip4RedirectHandler(aPacket, aInfo);
       
  7955             return 0;
       
  7956             }
       
  7957         // The only interesting thing is the Unreachable/Fragmentation needed
       
  7958         // (RFC-792 + RFC-1192)
       
  7959         if (aInfo.iType != KInet4ICMP_Unreachable || aInfo.iCode != 4)
       
  7960             return 0;
       
  7961         //
       
  7962         // Check the parameter as per RFC-1192 (additions to RFC-972)
       
  7963         if (mtu == 0)
       
  7964             mtu = 576;      // ICMP does not include next hop MTU, use 576
       
  7965         else
       
  7966             {
       
  7967             mtu &= 0xffff;  // Mask off the "unused high order bits"
       
  7968             if (mtu < STATIC_CAST(TUint,KInetMinMtu))
       
  7969                 return 0;   // Cannot be smaller than 68!
       
  7970             }           
       
  7971         }
       
  7972     else
       
  7973         return 0;
       
  7974     //
       
  7975     // A new minimum mtu value has been received...
       
  7976     //
       
  7977     //
       
  7978     // We assume the info still holds the original data as set in the
       
  7979     // interface.
       
  7980     //
       
  7981     const CIp6Interface *const iface = FindInterface(aInfo.iInterfaceIndex);
       
  7982     if (iface == NULL)
       
  7983         return 0;       // Can't locate interface (should not happen
       
  7984                         // unless interface actually died after this
       
  7985                         // packet got in).
       
  7986     //
       
  7987     // Poor man's Path MTU algorithm. Just maintain single Path MTU
       
  7988     // for a interface. [first obvious optimization would be to use
       
  7989     // interface MTU at least for the local addresses]. Enhance as
       
  7990     // needed later.. -- msa
       
  7991     //
       
  7992     if (mtu >= (TUint)iface->iPMtu)
       
  7993         return 0;       // Too Big error MUST NOT increase existing Path MTU!
       
  7994 
       
  7995     //
       
  7996     // Path MTU has been decreased, notify all affected flows!
       
  7997     //
       
  7998     iface->NotifyFlowsPmtu(mtu);
       
  7999 
       
  8000     // Store path mtu value to destination cache
       
  8001     if (iDestinationCache)
       
  8002         {
       
  8003         TInetAddr dst = TInetAddr::Cast(aInfo.iDstAddr);
       
  8004         const TCacheInfo *ci = iDestinationCache->Find(dst);
       
  8005 
       
  8006         // valid cached PMTU must not be increased
       
  8007         if (!ci || ci->iMetrics[TCacheInfo::EPathMTU] > mtu)
       
  8008             {
       
  8009             // Nothing useful to be done here with error code.
       
  8010             TRAP_IGNORE(iDestinationCache->SetL(dst, TCacheInfo::EPathMTU, mtu));
       
  8011             }
       
  8012         }
       
  8013 
       
  8014     return 0;
       
  8015     }
       
  8016 
       
  8017 
       
  8018 // CIp6Manager::MoveToHolding
       
  8019 // **************************
       
  8020 //
       
  8021 void CIp6Manager::MoveToHolding(CIp6Flow &aFlow) const
       
  8022     {
       
  8023     aFlow.iChanged = 1;         // When put on hold, always require a reconnect
       
  8024     if (iHoldingRoute == NULL)
       
  8025         return; // Should never happen...
       
  8026     if (aFlow.iStatus >= 0) // ..don't overwrite error states
       
  8027         aFlow.iStatus = EFlow_PENDING;
       
  8028 
       
  8029     if (aFlow.iRoute != iHoldingRoute)
       
  8030         {
       
  8031         // This is ugly: a flow can be in holding, but at arrival
       
  8032         // of router advertisement with default route, it will
       
  8033         // attach to the interface (and off holding). However, if
       
  8034         // source address is not available, it gets punted back
       
  8035         // to holding, with unfortunate side effect of resetting
       
  8036         // the time stamp and preventing expire. A somewhat ugly
       
  8037         // quick solution: time stamp is set only when it's zero,
       
  8038         // and RefreshFlow is changed to zero the stamp when it
       
  8039         // gets past source address selection... -- msa
       
  8040         if (aFlow.iTimeStamp == 0)
       
  8041             // NOTE: on rare accounts, TickCount can also be 0,
       
  8042             // but, it should not break things too much...
       
  8043             aFlow.iTimeStamp = User::TickCount();
       
  8044         iHoldingRoute->Attach(aFlow);
       
  8045         if (!iHoldingRoute->IsTimerActive())
       
  8046             iHoldingRoute->Timeout();
       
  8047         }
       
  8048     }
       
  8049 
       
  8050 void CIp6Manager::MoveToHolding(CIp6Route &aRoute) const
       
  8051     {
       
  8052     if (iHoldingRoute != &aRoute)
       
  8053         {
       
  8054         while (aRoute.iFlowList != NULL)
       
  8055             MoveToHolding(*aRoute.iFlowList);
       
  8056         }
       
  8057     }
       
  8058 
       
  8059 // CIp6Manager::ScanHoldings
       
  8060 // *************************
       
  8061 //
       
  8062 void CIp6Manager::ScanHoldings()
       
  8063     {
       
  8064     iScanHolding = 0;
       
  8065     if (!iHoldingRoute)
       
  8066         return;
       
  8067     TFlowNotifyList list;
       
  8068     for (CIp6Flow *f = iHoldingRoute->iFlowList; f != NULL; f = f->iNext)
       
  8069         list.Insert(*f);
       
  8070     list.Deliver(EFlow_READY);
       
  8071     }
       
  8072 
       
  8073 //
       
  8074 // CIp6Manager::GetInterfaceByNameL
       
  8075 // ********************************
       
  8076 /**
       
  8077 // Get interface by name (and create a new entry, if not found)
       
  8078 //
       
  8079 // @returns non-NULL always or leaves
       
  8080 */
       
  8081 CIp6Interface *CIp6Manager::GetInterfaceByNameL(const TDesC &aName)
       
  8082     {
       
  8083     //
       
  8084     // Look if the interface already exists
       
  8085     //
       
  8086     CIp6Interface **h, *iface;
       
  8087 
       
  8088     for (h = &iInterfaceList;; h= &iface->iNext)
       
  8089         {
       
  8090         if ((iface = *h) == NULL)
       
  8091             {
       
  8092             //
       
  8093             // A new interface, create an instance
       
  8094             //
       
  8095             // *NOTE*
       
  8096             //  1)  assume iInterfaceIndex is an ever increasing sequence
       
  8097             //      (some worry about wrap around... -- msa)
       
  8098             //  2)  new interfaces are always added to the *END* of
       
  8099             //      the list
       
  8100             //  =>  The interfaces on the list are *ALWAYS* in increasing
       
  8101             //      order by their iIndex fields!
       
  8102             //  **  The above FACT is relied on in other methods, such
       
  8103             //      as InterfaceInfo!
       
  8104             //
       
  8105             iface = new (ELeave) CIp6Interface(*this, ++iInterfaceIndex, aName);
       
  8106             iface->iNext = NULL;
       
  8107             iface->iNifUser = iNifUser[0];  // Doesn't matter whether IPv4 or IPv6 (it will be changed as needed).
       
  8108             ASSERT(iNifUser[0] != NULL);
       
  8109             *h = iface;
       
  8110             iface->Reset(); // ..some members have non-ZERO defauls, so Reset is also called!
       
  8111             break;
       
  8112             }
       
  8113         else if (aName.Compare(iface->iName) == 0)
       
  8114             break;      // Interface with specified name already exists
       
  8115         }
       
  8116     return iface;
       
  8117     }
       
  8118 
       
  8119 // CIp6Manager::RemoveInterface
       
  8120 // ****************************
       
  8121 // Brutally tear the specified interface down and release all associated resources
       
  8122 void CIp6Manager::RemoveInterface(CIp6Interface *aIf)
       
  8123     {
       
  8124     CIp6Interface **h, *iface;
       
  8125 
       
  8126     for (h = &iInterfaceList; (iface = *h) != NULL; h= &iface->iNext)
       
  8127         if (iface == aIf)
       
  8128             {
       
  8129             // Remove from the list and destroy!
       
  8130             *h = iface->iNext;
       
  8131             delete iface;
       
  8132             return;
       
  8133             }
       
  8134     // Should NEVER get here!
       
  8135     ASSERT(0);
       
  8136     }
       
  8137 
       
  8138 // CIp6Manager::FindRoute
       
  8139 // **********************
       
  8140 /**
       
  8141 // Locate route entry who has the longest matching
       
  8142 // prefix with destination. (A default route can be
       
  8143 // expressed with zero length prefix, which will match
       
  8144 // any address)
       
  8145 //
       
  8146 // Only interfaces with matching ScopeId are searched.
       
  8147 */
       
  8148 CIp6Route *CIp6Manager::FindRoute
       
  8149         (const TIp6Addr &aDst, const TUint32 aDstId, const TUint aDstType,
       
  8150          const TIp6Addr &aSrc, const TUint32 aSrcId) const
       
  8151     {
       
  8152     //
       
  8153     // Search Over all interfaces "within scope"
       
  8154     //
       
  8155     CIp6Route *route = NULL;
       
  8156 
       
  8157     if (aDstType > EScopeType_NET)
       
  8158         return NULL;
       
  8159 
       
  8160     if (!TIp46Addr::Cast(aSrc).IsUnspecified())
       
  8161         {
       
  8162         // Find route by source and destination (need to do the hard way in
       
  8163         // case we allow the same source address with multiple interfaces).
       
  8164         // [easy way would be: find interface with the address and just check
       
  8165         // route on it -- msa]
       
  8166         //
       
  8167         const TUint srcType = (TUint)(aSrc.Scope() - 1);
       
  8168         if (srcType > EScopeType_NET)
       
  8169             return NULL;
       
  8170 
       
  8171         for (const CIp6Interface *ifp = iInterfaceList; ifp != NULL; ifp = ifp->iNext)
       
  8172             {
       
  8173             if ((aSrcId == 0 || ifp->iScope[srcType] == 0 || ifp->iScope[srcType] == aSrcId) &&
       
  8174                 (aDstId == 0 || ifp->iScope[aDstType] == 0 || ifp->iScope[aDstType] == aDstId) &&
       
  8175                 ifp->IsMyAddress(aSrc))
       
  8176                 route = ifp->FindRoute(aDst, route);
       
  8177             }
       
  8178         }
       
  8179     else if (aSrcId != 0)
       
  8180         {
       
  8181         // When a source address is not specified, but source id is given, then it is
       
  8182         // assumed that the source ID is the interface index and will limit the route
       
  8183         // search to a specific interface.
       
  8184         for (const CIp6Interface *ifp = iInterfaceList; ifp != NULL; ifp = ifp->iNext)
       
  8185             if (ifp->iScope[0] == aSrcId)
       
  8186                 {
       
  8187                 route = ifp->FindRoute(aDst, route);
       
  8188                 break;
       
  8189                 }
       
  8190         }
       
  8191     else
       
  8192         {
       
  8193         // Find route by destination alone
       
  8194         for (const CIp6Interface *ifp = iInterfaceList; ifp != NULL; ifp = ifp->iNext)
       
  8195             {
       
  8196             if ((aDstId == 0 || ifp->iScope[aDstType] == 0 || ifp->iScope[aDstType] == aDstId))
       
  8197                 route = ifp->FindRoute(aDst, route);
       
  8198             }
       
  8199         }
       
  8200     return route;
       
  8201     }
       
  8202 
       
  8203 
       
  8204 // CIp6Manager::ProbeDestination
       
  8205 // *****************************
       
  8206 void CIp6Manager::ProbeDestination
       
  8207         (const TIp6Addr &aDst, const TUint32 aDstId, const TUint aDstType,
       
  8208          const TIp6Addr &aSrc, const TUint32 aSrcId) const
       
  8209     {
       
  8210     // No probing if destination is not fully defined
       
  8211 
       
  8212     if (!aDstId || aDstType > EScopeType_NET)
       
  8213         return;
       
  8214 
       
  8215     if (!TIp46Addr::Cast(aSrc).IsUnspecified())
       
  8216         {
       
  8217         // The source address limits the valid interfaces for probing.
       
  8218         //
       
  8219         const TUint srcType = (TUint)(aSrc.Scope() - 1);
       
  8220         if (srcType > EScopeType_NET)
       
  8221             return;
       
  8222 
       
  8223         for (CIp6Interface *ifp = iInterfaceList; ifp != NULL; ifp = ifp->iNext)
       
  8224             {
       
  8225             if (ifp->NeedsND() &&
       
  8226                 ifp->iScope[srcType] == aSrcId &&
       
  8227                 ifp->iScope[aDstType] == aDstId
       
  8228                 )
       
  8229                 {
       
  8230                 TIp6AddressInfo *info = ifp->IsMyAddress(aSrc);
       
  8231                 
       
  8232                 // We override the probe address setting for link local source addresses -
       
  8233                 // they are not routable and therefore useless otherwise.
       
  8234                 if( info && ( iProbeAddress || info->iIpv4LinkLocal ) )
       
  8235                     {
       
  8236                     (void)ifp->StartProbeND(aSrc, aDst);
       
  8237                     }
       
  8238                 }
       
  8239             }
       
  8240         }
       
  8241     else if (aSrcId != 0)
       
  8242         {
       
  8243         // When a source address is not specified, but source id is given, then it is
       
  8244         // assumed that the source ID is the interface index and will limit the
       
  8245         // search to a specific interface.
       
  8246         CIp6Interface *const ifp = FindInterface(aSrcId);
       
  8247         TIp6Addr src;
       
  8248         if (ifp && ifp->NeedsND())
       
  8249             {
       
  8250             if( ifp->SelectSource(src, aDst) )
       
  8251                 {
       
  8252                 if( iProbeAddress )
       
  8253                     {
       
  8254                     (void)ifp->StartProbeND(src, aDst);
       
  8255                     }
       
  8256                 else
       
  8257                     {
       
  8258                     TIp6AddressInfo *info = ifp->IsMyId( src ); // do not need to search anycast addresses
       
  8259                     
       
  8260                     // We override the probe address setting for link local source addresses -
       
  8261                     // they are not routable and therefore useless otherwise.
       
  8262                     if( info && info->iIpv4LinkLocal )
       
  8263                         {
       
  8264                         (void)ifp->StartProbeND(src, aDst);
       
  8265                         }
       
  8266                     }
       
  8267                 }
       
  8268             else
       
  8269                 {
       
  8270                 const TIp6AddressInfo* address = ifp->FindIpv4LinkLocalAddr();
       
  8271 
       
  8272                 // If no appropriate routable source address exists, start a probe if the interface
       
  8273                 // has an IPv4 link local address.
       
  8274                 if( address && address->IsAssigned() )
       
  8275                     {
       
  8276                     (void)ifp->StartProbeND(address->iId, aDst);
       
  8277                     }
       
  8278                 }
       
  8279             }
       
  8280         }
       
  8281     else
       
  8282         {
       
  8283         TBool probeStarted = EFalse;
       
  8284         
       
  8285         // Select by destination only.  If no source address can be found, start a probe
       
  8286         for (CIp6Interface *ifp = iInterfaceList; ifp != NULL; ifp = ifp->iNext)
       
  8287             {
       
  8288             if (ifp->NeedsND() && ifp->iScope[aDstType] == aDstId)
       
  8289                 {
       
  8290                 TIp6Addr src;
       
  8291                 if (ifp->SelectSource(src, aDst))
       
  8292                     {
       
  8293                     if( iProbeAddress )
       
  8294                         {
       
  8295                         (void)ifp->StartProbeND(src, aDst);
       
  8296                         
       
  8297                         probeStarted = ETrue;
       
  8298                         }
       
  8299                     else
       
  8300                         {
       
  8301                         TIp6AddressInfo *info = ifp->IsMyId( src ); // do not need to search anycast addresses
       
  8302                         
       
  8303                         // We override the probe address setting for link local source addresses -
       
  8304                         // they are not routable and therefore useless otherwise.
       
  8305                         if( info && info->iIpv4LinkLocal )
       
  8306                             {
       
  8307                             (void)ifp->StartProbeND(src, aDst);
       
  8308                         
       
  8309                             probeStarted = ETrue;
       
  8310                             }
       
  8311                         }
       
  8312                     }
       
  8313                 }
       
  8314             }
       
  8315             
       
  8316         // If no interface has an appropriate routable source address, start a probe
       
  8317         // on each interface with an IPv4 link local address.
       
  8318         if( !probeStarted )
       
  8319             {
       
  8320             for (CIp6Interface *ifp = iInterfaceList; ifp != NULL; ifp = ifp->iNext)
       
  8321                 {
       
  8322                 if (ifp->NeedsND() && ifp->iScope[aDstType] == aDstId)
       
  8323                     {
       
  8324                     const TIp6AddressInfo* address = ifp->FindIpv4LinkLocalAddr();
       
  8325 
       
  8326                     if( address && address->IsAssigned() )
       
  8327                         {
       
  8328                         (void)ifp->StartProbeND(address->iId, aDst);
       
  8329                         }
       
  8330                     }
       
  8331                 }
       
  8332             }
       
  8333         }
       
  8334     }
       
  8335 
       
  8336 
       
  8337 TInt CIp6Manager::GetDstCachePathMtu(const TIp6Addr& aDstAddress, TUint32 aScopeId) const
       
  8338 /**
       
  8339 Returns Path MTU value stored in destination cache with given IP address.
       
  8340 
       
  8341 @param aDstAddress  IP destination address to be searched from the destination cache.
       
  8342 @param aScopeId     Scope ID of the destination. RefreshFlow() has selected this.
       
  8343 
       
  8344 @return Path MTU if value was stored in destination cache. If destination cache is not available
       
  8345 or given address could not be found, 0 is returned.
       
  8346 */
       
  8347     {
       
  8348     if (!iDestinationCache)
       
  8349         {
       
  8350         return 0;
       
  8351         }
       
  8352         
       
  8353     TInetAddr dst(aDstAddress, 0);
       
  8354     dst.SetScope(aScopeId);
       
  8355     const TCacheInfo *cinfo = iDestinationCache->Find(dst);
       
  8356     LOG(TLogAddressPrefix logdst(dst)); // For logging, the destination address as a string.
       
  8357     if (!cinfo)
       
  8358         {
       
  8359         LOG(Log::Printf(_L("\t\tDstCache Path MTU for %S -- No match"), &logdst));
       
  8360         return 0;
       
  8361         }
       
  8362         
       
  8363     LOG(Log::Printf(_L("\t\tDstCache Path MTU for %S -- Found MTU = %d"),
       
  8364         &logdst, cinfo->iMetrics[TCacheInfo::EPathMTU]));
       
  8365 
       
  8366     return cinfo->iMetrics[TCacheInfo::EPathMTU];
       
  8367     }
       
  8368 
       
  8369 
       
  8370 void *CIp6Manager::GetApiL(const TDesC8& aApiName, TUint* aVersion)
       
  8371     {
       
  8372     if (aApiName == _L8("MEventService"))
       
  8373         {
       
  8374         if (!iEventManager)
       
  8375             {
       
  8376             User::Leave(KErrInetUnsupportedApi);
       
  8377             }
       
  8378         return EXPORT_API_L(MEventService, iEventManager, aVersion);
       
  8379         }
       
  8380 
       
  8381     if (aApiName == _L8("MNetworkInfo"))
       
  8382         return EXPORT_API_L(MNetworkInfo, this, aVersion);
       
  8383         
       
  8384     if (aApiName == _L8("MDestinationCache"))
       
  8385         {
       
  8386         // It is possible that the destination cache has not been instantiated
       
  8387         // (e.g. due to ini param), or its initialization has failed.
       
  8388         // The leave error below is not the most ideal, perhaps
       
  8389         if (!iDestinationCache)
       
  8390             {
       
  8391             User::Leave(KErrInetUnsupportedApi);
       
  8392             }
       
  8393         return EXPORT_API_L(MDestinationCache, iDestinationCache, aVersion);
       
  8394         }
       
  8395 
       
  8396     User::Leave(KErrInetUnsupportedApi);
       
  8397     // NOTREACHED
       
  8398     return NULL;
       
  8399     }
       
  8400 
       
  8401 
       
  8402 CIp6Route *CIp6Interface::FindNeighbor(const TIp6Addr &aDst) const
       
  8403     {
       
  8404     // Only a neighbor cache entry is accepted!
       
  8405     for (CIp6Route *rt = iRouteList; rt != NULL; rt = rt->iNext)
       
  8406         if (rt->IsHostRoute() && aDst.IsEqual(rt->iPrefix))
       
  8407             return rt;
       
  8408     return NULL;
       
  8409     }
       
  8410 
       
  8411 
       
  8412 // CIp6Interface::FindRoute
       
  8413 // ************************
       
  8414 CIp6Route *CIp6Interface::FindRoute(const TIp6Addr &aDst, CIp6Route *aRoute) const
       
  8415     /**
       
  8416     * Locate the best route from this interface matching the destination.
       
  8417     *
       
  8418     * @param aDst   The destination address
       
  8419     * @param aRoute The current best route, or NULL if none found yet.
       
  8420     *
       
  8421     * @return
       
  8422     * @li if no better route is found, the return value is aRoute.
       
  8423     * @li if a better route is found, return value is the new better route.
       
  8424     */
       
  8425     {
       
  8426     // The way sending packets is now implemented, requires that if the destionation
       
  8427     // is my own address, then the route assigned to the flow must indicate that
       
  8428     // (must be ELoopback). [This way, the destination doesn't need to be checked
       
  8429     // for every packet--a simple test for route type is enough].
       
  8430     //
       
  8431     // Address is my address, if the ID (which is not a proxy) matches my id AND,
       
  8432     // if the prefix part fully matches one of the ELoopback routes.
       
  8433     CIp6Route *rt = NULL; // silly GCC want's this to be silent...
       
  8434 
       
  8435     const TIp6AddressInfo *const id = IsMyId(aDst);
       
  8436     if (id && !id->IsProxy() && (rt = IsMyPrefix(aDst, *id)) != NULL)
       
  8437         {
       
  8438         // ..could test if id IsAssigned(), but only "wrong"
       
  8439         // thing that happens is, that a loopback route is returned
       
  8440         // for the flow and no packets with tentative address will
       
  8441         // go out! (and as "tentative" is very transient state,
       
  8442         // this should not happen easily)
       
  8443         //
       
  8444         // If a destination is my address on this interface,
       
  8445         // don't even consider any other routes.
       
  8446         //
       
  8447         return rt;
       
  8448         }
       
  8449     //
       
  8450     // The route with best weight is selected. The weight value is
       
  8451     // computed as follows
       
  8452     //  -2, if no route yet
       
  8453     //  -1, if route is not "reachable"
       
  8454     //  prefix length, if route is "reachable"
       
  8455     //
       
  8456     // "reachable" an internal concept to this function and is
       
  8457     // defined as: route is reachable if it is not a gateway route,
       
  8458     // or if it is a gateway route and a host route to the gateway
       
  8459     // exist with ISROUTE set!
       
  8460     //
       
  8461     // *NOTE* The gateway test intentionally excludes the ERedirect
       
  8462     // gateways!
       
  8463 
       
  8464 
       
  8465     TInt weight;
       
  8466     // If destination is IPv4 address, the route must
       
  8467     // match at least 96 bits to be acceptable!
       
  8468     const TInt min_match = aDst.IsV4Mapped() ? 96 : 0;
       
  8469 
       
  8470     if (aRoute == NULL)
       
  8471         weight = -2;
       
  8472     else
       
  8473         weight = (aRoute->iState != CIp6Route::EGateway || aRoute->iRouter) ? aRoute->iLength : -1;
       
  8474 
       
  8475     for (rt = iRouteList; rt != NULL; rt = rt->iNext)
       
  8476         {
       
  8477         if (rt->IsMyPrefix())
       
  8478             continue;   // Ignore "my prefix" entries. Looking for "true" routes only
       
  8479         if (rt->iIsProbing)
       
  8480             continue;   // Ignore "probing only" routes (ND host route).
       
  8481         if (min_match > rt->iLength)
       
  8482             continue;   // Ignore too short prefixes (IPv4 needs at least 96).
       
  8483 
       
  8484         const TInt w = (rt->iState != CIp6Route::EGateway || rt->iRouter) ? rt->iLength : -1;
       
  8485         if (weight > w)
       
  8486             continue;   // Already better route exists, no need to compare address!
       
  8487         if (rt->iPrefix.Match(aDst) < rt->iLength)
       
  8488             continue;           // Does not match (full prefix must match!)
       
  8489         //
       
  8490         // *NOTE* if aRoute == NULL, then weight == -2 and thus cannot be equal
       
  8491         // to w (always > -2) => No need to test if aRoute is NULL!!
       
  8492         // Metric only affects "reachable" routes (if it affected non-"reachable",
       
  8493         // system would never try an alternate gateway route with larger metric,
       
  8494         // even if the better metric route would fail consistently!) -- msa
       
  8495 //lint -e{613}
       
  8496         if (weight == w && w >= 0 && rt->iMetric > aRoute->iMetric)
       
  8497             continue;   // Weights are equal, previous route has better metric.
       
  8498 
       
  8499         // *WARNING* The above test causes the behaviour that the last matching
       
  8500         // route is returned, when none of the routers appear reachable. This
       
  8501         // is utilized by "SelectNexthop" to implement the Round-Robin attempts
       
  8502         // to contact routers, when none is reachable...
       
  8503 
       
  8504         aRoute = rt;
       
  8505         weight = w;
       
  8506         }
       
  8507     return aRoute;
       
  8508     }
       
  8509 
       
  8510 // CIp6Interface::GetDefGateway 
       
  8511 // ************************ 
       
  8512 // Get the default gateway address for this interface matching the gateway address type 
       
  8513 //  
       
  8514 void CIp6Interface::GetDefGateway(const TBool aIsIPv4, TInetAddr &aAddr) const 
       
  8515      { 
       
  8516      static const TIp6Addr prefix = {{{0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0}}}; 
       
  8517      TUint length = aIsIPv4 ? 96 : 0; 
       
  8518    
       
  8519      CIp6Route *located_rt = NULL; 
       
  8520      for (CIp6Route *rt = iRouteList; rt != NULL; rt = rt->iNext) 
       
  8521          { 
       
  8522          if (!rt->IsGateway()) 
       
  8523              continue; 
       
  8524    
       
  8525          if (length != rt->iLength) 
       
  8526              continue; // Ignore non-default routes 
       
  8527    
       
  8528          if (!aIsIPv4 && (rt->iPrefix.Match(prefix) < length)) 
       
  8529              continue; // Does not match (full prefix must match!) 
       
  8530    
       
  8531          if (located_rt && (rt->iMetric > located_rt->iMetric)) 
       
  8532              continue; // previous route has better metric 
       
  8533    
       
  8534          located_rt = rt; 
       
  8535          } 
       
  8536    
       
  8537      if (located_rt) 
       
  8538          located_rt->iAddress.GetAddress(aAddr); 
       
  8539      else 
       
  8540          aAddr.SetAddress(KInet6AddrNone); 
       
  8541       
       
  8542      } 
       
  8543 
       
  8544 // CIp6Interface::RouterChanged
       
  8545 // ****************************
       
  8546 void CIp6Interface::RouterChanged(CIp6Route *const aRouter)
       
  8547     /**
       
  8548     * Maintain iRouter pointers.
       
  8549     *
       
  8550     * A host route entry has been changed to a router or ceased
       
  8551     * to be a router. Update all gateway routes that would use
       
  8552     * this router by patching the iRouter entry
       
  8553     *
       
  8554     * When called, the iIsRouter value must be already set to
       
  8555     * the new value!
       
  8556     */
       
  8557     {
       
  8558     ASSERT(aRouter->IsHostRoute());
       
  8559     if (!aRouter->IsHostRoute())
       
  8560         return;     // Should never get here (must only be called with host routes)
       
  8561 
       
  8562     if (aRouter->iIsRouter)
       
  8563         {
       
  8564         iRouters++;
       
  8565         // Add/Overwrite pointer to the matching gateway entries
       
  8566         for (CIp6Route *rt = iRouteList; rt != NULL; rt = rt->iNext)
       
  8567             {
       
  8568             // There should be no pointers to this route before this operation!
       
  8569             ASSERT(rt->iRouter != aRouter);
       
  8570             if (rt->IsGateway() &&  // Only Gateway routes are affected!
       
  8571                 rt->iAddress.Ip6Address().IsEqual(aRouter->iPrefix))
       
  8572                 rt->iRouter = aRouter;
       
  8573             }
       
  8574         // Should check flows in iHoldingRoute, if any could use this router now?
       
  8575         }
       
  8576     else
       
  8577         {
       
  8578         iRouters--;
       
  8579         // Remove all references to the this router (if all is working as intended
       
  8580         // they should all be gateway entries and address should match, but to be
       
  8581         // safe, just remove all without testing (in NON-debug release)
       
  8582         //
       
  8583         CIp6Route **h, *rt;
       
  8584         for (h = &iRouteList; (rt = *h) != NULL; )
       
  8585             {
       
  8586             if (rt->iRouter == aRouter)
       
  8587                 {
       
  8588                 ASSERT(rt->IsGateway() && rt->iAddress.Ip6Address().IsEqual(aRouter->iPrefix));
       
  8589                 rt->iRouter = NULL;
       
  8590                 // Punt all flows, if any, to holding route!
       
  8591                 // (this action may need to be considered yet).
       
  8592                 Interfacer().MoveToHolding(*rt);
       
  8593                 if (rt->iState == CIp6Route::ERedirect)
       
  8594                     {
       
  8595                     // If a "redirect" route loses it's target router,
       
  8596                     // redirect is cancelled -- remove the redirect
       
  8597                     // route from the route list.
       
  8598                     *h = rt->iNext;
       
  8599                     delete rt;
       
  8600                     continue;
       
  8601                     }
       
  8602                 }
       
  8603             h = &rt->iNext;
       
  8604             }
       
  8605         }
       
  8606     }
       
  8607 
       
  8608 //
       
  8609 // CIp6Interface::SelectNextHop
       
  8610 // ****************************
       
  8611 // Returns NULL, if no usable next hop found!
       
  8612 CIp6Route *CIp6Interface::SelectNextHop(const TIp6Addr &aDst, const TIp6Addr &aSrc, CIp6Route *aRoute)
       
  8613     {
       
  8614     ASSERT(aRoute != NULL);
       
  8615 #ifdef _LOG
       
  8616     TLogAddressPrefix logtmp(aDst);
       
  8617     TLogAddressPrefix logprf(aRoute->iPrefix, aRoute->iLength);
       
  8618 #endif
       
  8619 
       
  8620     if (aRoute->IsGateway())
       
  8621         {
       
  8622 #ifdef _LOG
       
  8623         TLogAddressPrefix logsrc(aRoute->iAddress.Ip6Address());
       
  8624 //      Log::Printf(_L("\tNEXTHOP [%S] for [%S]  ROUTE %d [%S] to GATEWAY [%S]"),
       
  8625 //          &iName, &logtmp, aRoute->iIndex, &logprf, &logsrc);
       
  8626         Log::Printf(_L("\tIF %u [%S] NEXTHOP for [%S] is ROUTE %d [%S] to GATEWAY [%S]"),
       
  8627             iScope[0], &iName, &logtmp, aRoute->iIndex, &logprf, &logsrc);
       
  8628 #endif
       
  8629         if (aRoute->iRouter == NULL)
       
  8630             {
       
  8631             // None of possible routers have host entries.
       
  8632 
       
  8633             // Move the selected route to the front of the
       
  8634             // iRouteList to implement the "Round-Robin"
       
  8635             // requirement of default router selection
       
  8636             // THIS IS SOMEWHAT TRICKY! It depends on the
       
  8637             // behaviour of FindRoute() method to return the
       
  8638             // *LAST* matching route entry in case where no
       
  8639             // routers are reachable. -- msa
       
  8640             MoveToFront(aRoute);
       
  8641             // Locate the neighbour cache entry for the gate (or create one if not exist yet). Do not
       
  8642             // set or clear ISROUTER for IPv6 gateway! We don't know whether it is a router or not!
       
  8643             // With IPv4, there ND (=ARP) has no ISROUTER feature, so we just have to assume all
       
  8644             // IPv4 hosts in gateway routes are implicitly routers.
       
  8645             const TUint flags = aRoute->iAddress.Ip6Address().IsV4Mapped() ? KRouteAdd_ISROUTER : 0;
       
  8646             CIp6Route *const n = GetRoute(aRoute->iAddress.Ip6Address(), 128, flags);
       
  8647             if (n && n->iState == CIp6Route::EIncomplete)
       
  8648                 {
       
  8649                 //
       
  8650                 // Nothing is known about the neighbor yet, start ND
       
  8651                 //
       
  8652                 LOG(Log::Printf(_L("\tIF %u [%S] NEXTHOP ROUTER (ND ROUTE %u) needed for [%S]"), iScope[0], &iName, n->iIndex, &logsrc));
       
  8653                 n->StartND(aSrc);
       
  8654                 }
       
  8655             // If in above the neighbor cache already existed in some other state thatn EIncomplete,
       
  8656             // it means that the ISROUTER is not set for this host, and it cannot be used as a router
       
  8657             // currently. => Cannot use this gateway!
       
  8658             //
       
  8659             // Cannot assign the next hop to the gateway, because it is not yet known if
       
  8660             // it is actually a router! Keep in holding!
       
  8661             return NULL;
       
  8662             }
       
  8663         return aRoute;
       
  8664         }
       
  8665     if(!aRoute->IsOnlink())
       
  8666         {
       
  8667 #ifdef _LOG
       
  8668         // assume route prefix is in logtmp
       
  8669         if (aRoute->IsMyPrefix())
       
  8670             Log::Printf(_L("\tIF %u [%S] NEXTHOP for [%S] is LOOPBACK ROUTE %u [%S]"), iScope[0], &iName, &logtmp, aRoute->iIndex, &logprf);
       
  8671         else if (aRoute->iIsMulticast)
       
  8672             Log::Printf(_L("\tIF %u [%S] NEXTHOP for [%S] is MULTICAST ROUTE %u [%S]"), iScope[0], &iName, &logtmp, aRoute->iIndex, &logprf);
       
  8673         else if (aRoute->IsHostRoute())
       
  8674             Log::Printf(_L("\tIF %u [%S] NEXTHOP for [%S] is HOST ROUTE %u [%S]"), iScope[0], &iName, &logtmp, aRoute->iIndex, &logprf);
       
  8675         else
       
  8676             Log::Printf(_L("\tIF %u [%S] NEXTHOP for [%S] is NOT ONLINK ROUTE %u [%S]"), iScope[0], &iName, &logtmp, aRoute->iIndex, &logprf);
       
  8677 #endif
       
  8678         return aRoute;
       
  8679         }
       
  8680     // This route is for onlink determination. Finding this
       
  8681     // means that the destination/next hop is on link, but
       
  8682     // no Host route for it exists yet. Create the host route.
       
  8683     //
       
  8684     // Note: LinkLocal destination is not handled in any special
       
  8685     // way. Interface supporting link local (fe80::/10) destinations
       
  8686     // must define the ONLINK route for it!
       
  8687     LOG(Log::Printf(_L("\tIF %u [%S] NEXTHOP for [%S] ONLINK ROUTE %d [%S]"), iScope[0], &iName, &logtmp, aRoute->iIndex, &logprf));
       
  8688     //
       
  8689     // Create implicit host route entry, if ND is required on the interface
       
  8690     // (For non-ND interfaces, the route is used as is)
       
  8691     //
       
  8692     if (NeedsND() && !((TIp46Addr &)aDst).IsMulticast())
       
  8693         {
       
  8694         CIp6Route *const n = GetRoute(aDst, 128, KRouteAdd_NEIGHBOR);
       
  8695         if (n == NULL)
       
  8696             return NULL;
       
  8697         if (n->iState == CIp6Route::EIncomplete)
       
  8698             n->StartND(aSrc);
       
  8699         LOG(Log::Printf(_L("\tIF %u [%S] NEXTHOP HOSTROUTE (ND ROUTE %u)"), iScope[0], &iName, n->iIndex));
       
  8700         return n;
       
  8701         }
       
  8702     return aRoute;
       
  8703     }
       
  8704 
       
  8705 //
       
  8706 // CIp6Flow::SelectNextHop
       
  8707 // ***********************
       
  8708 void CIp6Flow::SelectNextHop()
       
  8709     {
       
  8710     const TIp6Addr &dst = iStart.ip6.DstAddr();
       
  8711     // For log prints, have destination address as a string.
       
  8712     LOG(TLogAddressPrefix log_dst(dst));
       
  8713 
       
  8714     // Assume iRoute determines the route and interface. Limit nexthop
       
  8715     // selection to that route only!
       
  8716     for (;/* JUST FOR BREAK EXITS */;)
       
  8717         {
       
  8718         if (iRoute == NULL)
       
  8719             {
       
  8720             LOG(Log::Printf(_L("\t\tFlow[%u] OOPS? Route is NULL for %S"), this, &log_dst));
       
  8721             break;  // -- no route attached
       
  8722             }
       
  8723         CIp6Interface &iface = iRoute->iInterface;
       
  8724 
       
  8725         if (!iStart.iSourceSet)
       
  8726             {
       
  8727             LOG(Log::Printf(_L("\t\tFlow[%u] IF %d [%S] has no source address for %S"), this, iface.iScope[0], &iface.iName, &log_dst));
       
  8728             // If the source address cannot be assigned to this flow,
       
  8729             // punt the flow back to holding route (do not leave it
       
  8730             // attached to this interface). The reason is, for example
       
  8731             // PPP: 
       
  8732             // - has a separate interface for IPv4 and IPv6
       
  8733             // - if IPv6 interface installs default route before IPv4
       
  8734             //   has been configured, then IPv4 flows will try to
       
  8735             //   attach to the IPv6 interface, but fail due to
       
  8736             //   source address
       
  8737             // - however, if they are not moved to the holding route
       
  8738             //   they are stuck forever into the IPv6, even after the
       
  8739             //   real IPv4 becomes configured
       
  8740             // - *NOTE* IPv4 is just a case where a problem was observed,
       
  8741             //   there may be other situations which would fail with IPv6
       
  8742             //   in similar ways (choosing wrong interface based on
       
  8743             //   incomplete configuration), thus no special kludge
       
  8744             //   just for IPv4 is not designed -- msa
       
  8745             // The "punt" has unfortunate side effect for ethernet:
       
  8746             // - when ethernet comes up and a flow is punted to the
       
  8747             //   holding because DAD has not yet completed, the flow
       
  8748             //   is not wakened when DAD completes, unless DAD completion
       
  8749             //   also does a ScanHolding() [see Timeout()/DAD].
       
  8750             //   [Logically DAD completion should only be concern of
       
  8751             //   flows attached to the interface, but this punting
       
  8752             //   changes that... -- msa]
       
  8753             break;
       
  8754             }
       
  8755         if (iStart.iInterfaceIndex != iface.iScope[0])
       
  8756             {
       
  8757             LOG(Log::Printf(_L("\t\tFlow[%u] Route lost, interface %u changed to IF %u [%S] for %S"),
       
  8758                 this, iStart.iInterfaceIndex, iface.iScope[0], &iface.iName, &log_dst));
       
  8759             break;  // -- wrong interface (route was deleted probably)
       
  8760             }
       
  8761         CIp6Route *const route = iface.SelectNextHop(dst, iStart.ip6.SrcAddr(), iRoute);
       
  8762         if (iRoute == route)
       
  8763             return; // -- route not changed, all OK.
       
  8764         if (!route)
       
  8765             {
       
  8766             LOG(Log::Printf(_L("\t\tFlow[%u] IF %u [%S] has no ND entry for %S"), this, iface.iScope[0], &iface.iName, &log_dst));
       
  8767             break;  // -- no suitable route for the destination
       
  8768             }
       
  8769         //
       
  8770         // Route changed (into neighbor cache host route)
       
  8771         //
       
  8772         route->Attach(*this);
       
  8773         return;
       
  8774         }
       
  8775     iInterfacer.MoveToHolding(*this);
       
  8776     }
       
  8777 
       
  8778 //
       
  8779 // CIp6Interface::GetRoute
       
  8780 // ***********************
       
  8781 /**
       
  8782 // Insert a route entry to direct packets for a
       
  8783 // matching prefix to a specific named interface.
       
  8784 // (Interface is only activated after there a flow is
       
  8785 // activated to this route).
       
  8786 //
       
  8787 // A new route is NOT created if an identical route pointing
       
  8788 // to this same interface exists. In such case, the lifetime
       
  8789 // of the route is just updated (when lifetimes are implemented)
       
  8790 // It is allowed to have multiple routes with same prefix
       
  8791 // pointing to a *different* interface.
       
  8792 //
       
  8793 // NOTE:
       
  8794 //      This "add front" feature is part of the specification
       
  8795 //      and relied by some other parts. Beware of changing it!
       
  8796 //
       
  8797 // @return NULL or the pointer to the updated/created route entry
       
  8798 */
       
  8799 CIp6Route *CIp6Interface::GetRoute(const TIp6Addr &aAddr, TInt aPrefix, TUint aFlags, const TSockAddr *const aGateway, const TLifetime *const aLifetime)
       
  8800     {
       
  8801     CIp6Manager &mgr = Interfacer();
       
  8802     const TLifetime lifetime = aLifetime ? *aLifetime : KLifetimeForever;
       
  8803     const TUint rtype = aFlags & (KRouteAdd_EXTENSIONMASK | KRouteAdd_TYPEMASK);
       
  8804 
       
  8805     // Initial state can only be (HOST, ONLINK, GATEWAY, MYPREFIX) with possible
       
  8806     // extension bits. In debug version, just panic the operation, if extra bits
       
  8807     // is present in the state. In production, the trunctated value is used as is.
       
  8808     ASSERT(rtype == (aFlags & KRouteAdd_STATEMASK));
       
  8809 
       
  8810     const TLinkAddr KLinkAddr;
       
  8811     const TLinkAddr &gate = aGateway ? TLinkAddr::Cast(*aGateway) : KLinkAddr;
       
  8812 
       
  8813     TInt notifytype = EventTypeAdd;
       
  8814 
       
  8815     CIp6Route *rt;
       
  8816     for (CIp6Route **h = &iRouteList; ; h = &rt->iNext)
       
  8817         {
       
  8818         if ((rt = *h) == NULL)
       
  8819             {
       
  8820             //
       
  8821             // 1) Don't create entry with zero lifetime (call was just a Remove
       
  8822             //    route request in disguise.
       
  8823             // 2) Don't create entry if the call was "update existing only"
       
  8824             //
       
  8825             if (lifetime == 0 || (aFlags & KRouteAdd_UPDATEONLY) != 0)
       
  8826                 return NULL;
       
  8827             //
       
  8828             // This a new route, create it here
       
  8829             //
       
  8830             rt = new CIp6Route(++mgr.iRouteIndex, mgr, aAddr, aPrefix, *this);
       
  8831             if (rt == NULL)
       
  8832                 return NULL;
       
  8833             rt->iState = (CIp6Route::TState)rtype;
       
  8834 
       
  8835             if (TIp46Addr::Cast(aAddr).IsMulticast())
       
  8836                 rt->iIsMulticast = 1;
       
  8837             rt->iIsProbing = (aFlags & KRouteAdd_PROBINGONLY) != 0;
       
  8838             break;
       
  8839             }
       
  8840         else if (rt->iLength == aPrefix &&
       
  8841                  rt->ExtendedType() == rtype &&
       
  8842                  rt->iPrefix.Match(aAddr) >= aPrefix &&
       
  8843                 // Require gateway match only for "true" gateway entries!
       
  8844                 // (otherwise we never find the incomplete hostroutes, or
       
  8845                 // changed link layer addresses, because aGateway does not
       
  8846                 // match in those cases...). Note, specially that ERedirect
       
  8847                 // gateways do not require match on address!
       
  8848                 (rtype != CIp6Route::EGateway || rt->iAddress.Match(gate)))
       
  8849             {
       
  8850             // Somewhat dubious, but remove the the route from
       
  8851             // the current position (and it will be reinserted
       
  8852             // to the front. This might give priority to the last
       
  8853             // advertised default route, for example... -- msa
       
  8854             *h = rt->iNext;
       
  8855             // Should check the state matches the aFlags?? -- msa
       
  8856 
       
  8857             notifytype = EventTypeModify;
       
  8858                 
       
  8859             if (lifetime == 0)
       
  8860                 {
       
  8861                 LOG(rt->LogRoute(0));
       
  8862                 //
       
  8863                 // Delete matching route, if lifetime is ZERO
       
  8864                 //
       
  8865                 if (rt->iIsRouter)
       
  8866                     {
       
  8867                     rt->iIsRouter = 0;
       
  8868                     RouterChanged(rt);
       
  8869                     }
       
  8870                 //
       
  8871                 // If any flows are attached to the route that is being removed,
       
  8872                 // move them all into the holding route with PENDING status.
       
  8873                 //
       
  8874                 // Note: holding is *ALWAYS* non-NULL. The only time holding
       
  8875                 // can be NULL, is when it is being created by InitL(), and in
       
  8876                 // that case GetRoute() *NEVER* gets into this branch! -- msa
       
  8877                 //
       
  8878                 mgr.MoveToHolding(*rt);
       
  8879 
       
  8880                 // Send notification about removed route to event manager
       
  8881                 NotifyRouteEvent(EventTypeDelete, rt);
       
  8882 
       
  8883                 delete rt;
       
  8884                 return NULL;
       
  8885                 }
       
  8886             break;
       
  8887             }
       
  8888         }
       
  8889         
       
  8890     //
       
  8891     // Attach the route (new or some old) to front of the route list
       
  8892     //
       
  8893     rt->iNext = iRouteList;
       
  8894     iRouteList = rt;
       
  8895 
       
  8896     //
       
  8897     // Load gateway address, if specified
       
  8898     //
       
  8899     if (rt->Update(aFlags, aGateway, aLifetime) || notifytype == EventTypeAdd)
       
  8900         {
       
  8901         LOG(rt->LogRoute(lifetime));
       
  8902         rt->NotifyFlows(EFlow_READY);
       
  8903 
       
  8904         // Send notification about new route to event manager
       
  8905         NotifyRouteEvent(notifytype, rt, lifetime);
       
  8906         }
       
  8907 
       
  8908     return rt;
       
  8909     }
       
  8910 
       
  8911 void CIp6Interface::NotifyRouteEvent(TUint aEventType, const CIp6Route *aRoute,
       
  8912                      const TLifetime /*aLifetime*/) const
       
  8913 /**
       
  8914 Sends notification about event on routing table (add, delete, change) to event manager.
       
  8915 Event manager distributes the event to interested plugins.
       
  8916 This method handles two classes of notifications EClassRoute for events on route information,
       
  8917 and EClassNeighbour for events on changed information in neighbour cache.
       
  8918 
       
  8919 @param aEventType   EventTypeAdd, EventTypeDelete, or EventTypeModify.
       
  8920 @param aRoute       Pointer to routing table entry that has changed.
       
  8921 @param aLifetime    Not used. Will be removed.
       
  8922 */
       
  8923     {
       
  8924     CIp6Manager &mgr = Interfacer();
       
  8925     TUint evclass = aRoute->IsHostRoute() ? EClassNeighbour : EClassRoute;
       
  8926 
       
  8927     // If there is no event manager, or if there are no registered listeners, we can exit
       
  8928     // the function right away
       
  8929     if (!mgr.EventManager())
       
  8930         {
       
  8931         return;
       
  8932         }
       
  8933 
       
  8934     if (mgr.EventManager()->IsEmpty(evclass))
       
  8935         {
       
  8936         return;
       
  8937         }
       
  8938 
       
  8939     void *ptr = NULL;   // Either TInetRouteInfo or TInetNeighbourInfo
       
  8940     TTime stamp;
       
  8941     stamp.UniversalTime();
       
  8942     TInetRouteInfo rinfo;
       
  8943     TInetNeighbourInfo nginfo;
       
  8944     if (evclass == EClassRoute)
       
  8945         {
       
  8946         aRoute->FillRouteInfo(rinfo, Elapsed(stamp));
       
  8947         ptr = &rinfo;
       
  8948         }
       
  8949     else
       
  8950         {
       
  8951         aRoute->FillNeighbourInfo(nginfo, Elapsed(stamp));
       
  8952         ptr = &nginfo;
       
  8953         }
       
  8954     
       
  8955     mgr.EventManager()->Notify(evclass, aEventType, ptr);
       
  8956     }
       
  8957 
       
  8958 
       
  8959 // CIp6Manager::AddRouteL
       
  8960 // **********************
       
  8961 // This creates both route and interface (if interface didn't exist before)
       
  8962 void CIp6Manager::AddRouteL
       
  8963     (const TIp6Addr &aAddr, TInt aPrefix,const TDesC &aName, TUint aFlags,
       
  8964      const TSockAddr *const aGateway, const TUint32 *const aLifetime)
       
  8965     {
       
  8966     CIp6Interface *const iface = GetInterfaceByNameL(aName);
       
  8967     const CIp6Route *const route = iface->GetRoute(aAddr, aPrefix, aFlags, aGateway, aLifetime);
       
  8968     if (route)
       
  8969         {
       
  8970         if (route->IsMyPrefix())
       
  8971           // FIXME: Temporary fix to make node-local multicast through loopback interface to work
       
  8972           iface->AddId(aAddr, aPrefix < 128 ? 128 : 0); // (attempt to make at least one id implicitly defined
       
  8973                                         // so that a single AddRouteL can be used to create
       
  8974                                         // a "virtual" or loopback interface.
       
  8975         ScanHoldings(); // ...routes might have changed by above
       
  8976         }
       
  8977     }
       
  8978 
       
  8979 // CIp6Manager::CheckRoute
       
  8980 // ***********************
       
  8981 /**
       
  8982 // Find a route by destination address and get a matching source address.
       
  8983 // @return
       
  8984 // @li  KErrNone, if route and source address found
       
  8985 // @li  KErrNotFound, otherwise
       
  8986 */
       
  8987 TInt CIp6Manager::CheckRoute(const TIp6Addr &aAddr, const TUint32 aScopeId, TIp6Addr &aSrc) const
       
  8988     {
       
  8989     const CIp6Route *const route = FindRoute(aAddr, aScopeId, (TUint)(aAddr.Scope()-1));
       
  8990     if (route && route->iInterface.SelectSource(aSrc, aAddr))
       
  8991         return KErrNone;    // Route and source address found!
       
  8992     return KErrNotFound;    // Route or source address not found!
       
  8993     }
       
  8994 
       
  8995 //
       
  8996 // CIp6Interface::RemoveRoute
       
  8997 // **************************
       
  8998 // Remove a specific route
       
  8999 void CIp6Interface::RemoveRoute(CIp6Route *aRoute)
       
  9000     {
       
  9001     CIp6Route **h, *rt;
       
  9002     for (h = &iRouteList; (rt = *h) != NULL; h = &rt->iNext)
       
  9003         {
       
  9004         if (rt == aRoute)
       
  9005             {
       
  9006             *h = rt->iNext;
       
  9007             LOG(rt->LogRoute(0));
       
  9008 
       
  9009             if (rt->iIsRouter)
       
  9010                 {
       
  9011                 rt->iIsRouter = 0;
       
  9012                 RouterChanged(rt);  // iIsRouter: "1 -> 0" 
       
  9013                 }
       
  9014             // Holding route should really never be deleted through this!
       
  9015             ASSERT(rt != Interfacer().iHoldingRoute);
       
  9016             // Punt flows into holding for next hop selection (need ScanHolding?)
       
  9017             if (rt != Interfacer().iHoldingRoute)
       
  9018                 Interfacer().MoveToHolding(*rt);
       
  9019 
       
  9020             // Send notification to event manager
       
  9021             NotifyRouteEvent(EventTypeDelete, rt);
       
  9022 
       
  9023             delete rt;
       
  9024             break;
       
  9025             }
       
  9026         }
       
  9027     }
       
  9028 
       
  9029 // CIp6Interface::MoveToFront
       
  9030 // **************************
       
  9031 /**
       
  9032 // Move the specific route to the first in the list. The
       
  9033 // route SHOULD be in the list, but if not, nothing happens
       
  9034 //
       
  9035 // (currently only used by select next hop, in rare occasions)
       
  9036 */
       
  9037 void CIp6Interface::MoveToFront(CIp6Route *aRoute)
       
  9038     {
       
  9039     CIp6Route **h, *rt;
       
  9040     for (h = &iRouteList; (rt = *h) != NULL; h = &rt->iNext)
       
  9041         {
       
  9042         if (rt == aRoute)
       
  9043             {
       
  9044             *h = rt->iNext;
       
  9045             rt->iNext = iRouteList;
       
  9046             iRouteList = rt;
       
  9047             break;
       
  9048             }
       
  9049         }
       
  9050     }
       
  9051 
       
  9052 //
       
  9053 // CIp6Manager::LocalScope
       
  9054 // ***********************
       
  9055 /**
       
  9056 // @returns non-zero scope id, if aAddr is a valid source address
       
  9057 // for packets originating from this node,
       
  9058 // and ZERO otherwise.
       
  9059 */
       
  9060 TUint32 CIp6Manager::LocalScope(const TIp6Addr &aAddr, const TUint32 aLock, const TScopeType aLockType) const
       
  9061     {
       
  9062     const TUint scope = (TUint)(aAddr.Scope()-1);
       
  9063     if (scope > EScopeType_NET)
       
  9064         return 0;   // Bad Address
       
  9065 
       
  9066     for (const CIp6Interface *iface = iInterfaceList;iface != NULL; iface = iface->iNext)
       
  9067         {
       
  9068         if ((aLock == 0 || iface->iScope[aLockType] == 0 || iface->iScope[aLockType] == aLock) &&
       
  9069             iface->IsMyAddress(aAddr))
       
  9070             // iface->iScope[scope] can be ZERO for looback (and similar *wild*
       
  9071             // interface). Return the default non-zero ID value in such case.
       
  9072             // (it will match this same network).
       
  9073             return iface->iScope[scope] ? iface->iScope[scope] : KDefaultNetworkId;
       
  9074         }
       
  9075     return 0;
       
  9076     }
       
  9077 
       
  9078 //
       
  9079 // CIp6Manager::RemoteScope
       
  9080 // ************************
       
  9081 // Determine the default scope id for a destination address.
       
  9082 //
       
  9083 // *NOTE* This does not check whether a matching interface actually exists!
       
  9084 //
       
  9085 TUint32 CIp6Manager::RemoteScope(const TIp6Addr &aAddr, const TUint32 aLock, const TScopeType aLockType) const
       
  9086     {
       
  9087     const CIp6Route *const rt = FindRoute(aAddr, aLock, aLockType);
       
  9088     if (rt == NULL)
       
  9089         return 0;
       
  9090 
       
  9091     // If rt non-null, then the scope index below will be valid (no need to check!)
       
  9092     const TUint scope_id = rt->iInterface.iScope[aAddr.Scope() - 1];
       
  9093 
       
  9094     // iface can be ZERO for looback (and similar *wild*
       
  9095     // interface). Return the default non-zero ID value in such case.
       
  9096     // (it will match this same network).
       
  9097     return scope_id ? scope_id : KDefaultNetworkId;
       
  9098     }
       
  9099 
       
  9100 // CIp6Manager::IsForMe
       
  9101 // ********************
       
  9102 // (private help utility)
       
  9103 //
       
  9104 // @returns
       
  9105 // @li != 0 (= interface index), if address is for me
       
  9106 // @li == 0, if address is not for me
       
  9107 //
       
  9108 #ifdef WEAK_ES
       
  9109 TUint32 CIp6Manager::IsForMe
       
  9110     (const TIp6Addr &aAddr, const CIp6Interface *const aSrcIf, const TUint32 aScopeId, const TScopeType aType) const
       
  9111 #else
       
  9112 TUint32 CIp6Manager::IsForMe(const TIp6Addr &aAddr, const CIp6Interface *const aSrcIf) const
       
  9113 #endif
       
  9114     {
       
  9115     //
       
  9116     // Check the original interface first, as this is the
       
  9117     // most common case.
       
  9118     //
       
  9119     if (aSrcIf->IsForMeAddress(aAddr))
       
  9120         return aSrcIf->iScope[0];
       
  9121 
       
  9122 #ifdef WEAK_ES
       
  9123     //
       
  9124     // In weak ES model, incoming packet can be accepted, even
       
  9125     // if destination address is assigned to another interface
       
  9126     //
       
  9127     // *NOTE*
       
  9128     //  the scope check does limit the range! So, this is not
       
  9129     //  exactly the weak model either.
       
  9130     //
       
  9131     // *NOTE*
       
  9132     //  the scope test is for strict equality! Thus, this WILL not
       
  9133     //  match addresses on loopback interfaces (unless the
       
  9134     //  original incoming interface was also a loopback--in
       
  9135     //  which case it should have already been dealt in above
       
  9136     //  test for original interface!)
       
  9137     //
       
  9138     for (const CIp6Interface *iface = iInterfaceList; iface != NULL; iface = iface->iNext)
       
  9139         if (iface->iScope[aType] == aScopeId && iface != aSrcIf && iface->IsForMeAddress(aAddr))
       
  9140             return iface->iScope[0];
       
  9141 #endif
       
  9142     return 0;
       
  9143     }
       
  9144 
       
  9145 //
       
  9146 // CIp6Manager::IsForMeAddress
       
  9147 // ***************************
       
  9148 /**
       
  9149 // Returns the interface index, if aAddr selects the current node
       
  9150 // (packets having this address as a destination are intended for me)
       
  9151 //
       
  9152 // @returns
       
  9153 //  @li != 0 (= interface index), if address is for me
       
  9154 //  @li == 0, if address is not for me
       
  9155 */
       
  9156 TUint32 CIp6Manager::IsForMeAddress(const TIp6Addr &aAddr, const TUint32 aInterfaceIndex) const
       
  9157     {
       
  9158     if (aInterfaceIndex == 0)
       
  9159         {
       
  9160         for (const CIp6Interface *iface = iInterfaceList; iface != NULL; iface = iface->iNext)
       
  9161             if (iface->IsForMeAddress(aAddr))
       
  9162                 return iface->iScope[0];
       
  9163         return 0;
       
  9164         }
       
  9165 
       
  9166     const CIp6Interface *const ifp = FindInterface(aInterfaceIndex);
       
  9167     if (ifp == NULL)
       
  9168         return 0;   // Cannot locate interface!
       
  9169 #ifdef WEAK_ES
       
  9170     const TUint scope = (TUint)(aAddr.Scope() - 1);
       
  9171     if (scope > EScopeType_NET)
       
  9172         return 0;   // Invalid address
       
  9173     return IsForMe(aAddr, ifp, ifp->iScope[scope], (TScopeType)scope);
       
  9174 #else
       
  9175     return IsForMe(aAddr, ifp);
       
  9176 #endif
       
  9177     }
       
  9178 
       
  9179 // CIp6Manager::IsForMePacket
       
  9180 // **************************
       
  9181 /**
       
  9182 // Complete scopes into the info and check if received packet as described by aInfo is for me.
       
  9183 //
       
  9184 // @return
       
  9185 //  @li -1 if incoming interface or addresses are not valid (drop packet!)
       
  9186 //  @li =0 if packet is not for me
       
  9187 //  @li =1 if packet is for me
       
  9188 */
       
  9189 TInt CIp6Manager::IsForMePacket(RMBufRecvInfo &aInfo) const
       
  9190     {
       
  9191     const CIp6Interface *const ifp = FindInterface(aInfo.iInterfaceIndex);
       
  9192     if (ifp == 0)
       
  9193         return -1;  // Cannot locate interface!
       
  9194 
       
  9195     LOG(PktLog(_L("\tIF %u [%S] RECV prot=%d src=%S dst=%S len=%d"), aInfo, ifp->iScope[0], ifp->iName));
       
  9196 
       
  9197     const TIp6Addr &src = TInetAddr::Cast(aInfo.iSrcAddr).Ip6Address();
       
  9198     const TIp6Addr &dst = TInetAddr::Cast(aInfo.iDstAddr).Ip6Address();
       
  9199 
       
  9200         {
       
  9201         //
       
  9202         // Fix source scope id into info block
       
  9203         //
       
  9204         const TUint scope = src.Scope() - 1;
       
  9205         if (scope > EScopeType_NET)
       
  9206             return -1;  // Invalid source scope
       
  9207         else if (scope == EScopeType_IF &&
       
  9208                 !TIp46Addr::Cast(src).IsUnspecified() &&
       
  9209                 !ifp->IsMyAddress(src))
       
  9210             return -1;  // Invalid source address (loopback address from wrong interface!)
       
  9211         TInetAddr::Cast(aInfo.iSrcAddr).SetScope(ifp->iScope[scope]);
       
  9212         }
       
  9213     //
       
  9214     // Fix destination scope id into info block
       
  9215     //
       
  9216     const TUint scope = (TUint)(dst.Scope() - 1);
       
  9217     if (scope > EScopeType_NET)
       
  9218         return -1;  // Invalid destination scope
       
  9219     const TUint dstId = ifp->iScope[scope];
       
  9220     TInetAddr::Cast(aInfo.iDstAddr).SetScope(dstId);
       
  9221 
       
  9222 #ifdef WEAK_ES
       
  9223     return IsForMe(dst, ifp, dstId, (TScopeType)scope) != 0;
       
  9224 #else
       
  9225     return IsForMe(dst, ifp) != 0;
       
  9226 #endif
       
  9227     }
       
  9228 
       
  9229 // MagicSetAddress
       
  9230 // ***************
       
  9231 // A static help routine to load TSockAddr address from a prefix
       
  9232 //
       
  9233 static void MagicSetAddress(TSockAddr &aAddr, const TIp6Addr &aSrc, TUint aLength, TSockAddr *aMask = NULL)
       
  9234     {
       
  9235     //
       
  9236     // Make aAddr address family to either IPv4 or IPv6 depending
       
  9237     // on whether aSrc is V4 mapped address or not.
       
  9238     //
       
  9239     if (aSrc.IsV4Mapped())
       
  9240         {
       
  9241         ((TInetAddr &)aAddr).SetAddress(
       
  9242             (aSrc.u.iAddr8[12] << 24) |
       
  9243             (aSrc.u.iAddr8[13] << 16) |
       
  9244             (aSrc.u.iAddr8[14] << 8) |
       
  9245             aSrc.u.iAddr8[15]);
       
  9246         if (aMask)
       
  9247             {
       
  9248             const TInt shift = 32 - (aLength - 96);
       
  9249             ((TInetAddr *)aMask)->SetAddress(shift > 31 ? 0 : ~0L << shift);
       
  9250             }
       
  9251         }
       
  9252     else
       
  9253         {
       
  9254         ((TInetAddr &)aAddr).SetAddress(aSrc);
       
  9255         if (aMask)
       
  9256             ((TInetAddr *)aMask)->PrefixMask(aLength);
       
  9257         }
       
  9258     }
       
  9259 
       
  9260 // MagicGetAddress
       
  9261 // ***************
       
  9262 /**
       
  9263 // Convert Address/Mask pair into Address and prefix, while doing some
       
  9264 // IPv4/IPv6 unifications.
       
  9265 //
       
  9266 // @returns the prefix length (the number of leftmost 1-bits in the mask)
       
  9267 //  @li < 0, (KErrArgument) the address family of addr or mask is not KAfInet6,
       
  9268 //       KAfInet or Unspecified
       
  9269 //  @li = 0, if mask is unspecified (or if leftmost bit is zero)
       
  9270 //  @li = 1..128, the prefix length
       
  9271 //  @li = 129 addr is unspecified family (mask is ignored)
       
  9272 */
       
  9273 static TInt MagicGetAddress(TIp6Addr &aResult, const TInetAddr &aAddr, const TInetAddr &aMask)
       
  9274     {
       
  9275     //
       
  9276     // Convert aAddr into plain IPv6 address
       
  9277     //
       
  9278     if (aAddr.Family() == KAfInet)
       
  9279         {
       
  9280         TInetAddr tmp(aAddr);
       
  9281         tmp.ConvertToV4Mapped();
       
  9282         aResult = tmp.Ip6Address();
       
  9283         }
       
  9284     else if (aAddr.Family() == KAfInet6)
       
  9285         aResult = aAddr.Ip6Address();
       
  9286     else if (aAddr.Family() == KAFUnspec)
       
  9287         return 129;     // Special value to indicate: no address/prefix present
       
  9288     else
       
  9289         return KErrArgument;    // Invalid Address
       
  9290     //
       
  9291     // Convert aMask into prefix length (ugh!)
       
  9292     //
       
  9293     if (aMask.Family() == KAfInet)
       
  9294         return 96 + MaskLength(aMask.Address());
       
  9295     else if (aMask.Family() == KAfInet6)
       
  9296         return MaskLength(aMask.Ip6Address());
       
  9297     else if (aMask.Family() == KAFUnspec)
       
  9298         return 0;
       
  9299     return KErrArgument;        // Invalid aMask!
       
  9300     }
       
  9301 
       
  9302 
       
  9303 void CIp6Route::FillRouteInfo(TInetRouteInfo &rinfo, TLifetime aReftime) const
       
  9304 /**
       
  9305 Fill TInetRouteInfo struct based on this route.
       
  9306 
       
  9307 @param rinfo    struct to be filled by the route information.
       
  9308 @param aRefTime reference time used in lifetime calculation. It should refer to the time
       
  9309                 the network interface has been up.
       
  9310 */
       
  9311     {
       
  9312     rinfo.iType = 0;
       
  9313     rinfo.iState = iState;
       
  9314     rinfo.iMetric = iMetric;
       
  9315     rinfo.iDstAddr = iPrefix;
       
  9316     rinfo.iPrefixLen = iLength;
       
  9317     rinfo.iInterface = iInterface.Index();
       
  9318     rinfo.iScopeId = iInterface.Scope((TScopeType)(iPrefix.Scope()-1));
       
  9319     rinfo.iGateway = iAddress.Ip6Address();
       
  9320     rinfo.iIndex = iIndex;
       
  9321 
       
  9322     if (iLifetime.iPreferred != KLifetimeForever)
       
  9323       {
       
  9324         rinfo.iLifetime = (iLifetime.iPreferred > aReftime) ?
       
  9325                 iLifetime.iPreferred - aReftime : 0;
       
  9326       }
       
  9327     else
       
  9328       {
       
  9329         rinfo.iLifetime = KLifetimeForever;
       
  9330       }
       
  9331       
       
  9332     if (iLifetime.iDeprecated)
       
  9333         rinfo.iType |= (TUint32)TInetRouteInfo::EDeprecated;
       
  9334     }
       
  9335 
       
  9336 
       
  9337 void CIp6Route::FillNeighbourInfo(TInetNeighbourInfo &nginfo, TLifetime aReftime) const
       
  9338 /**
       
  9339 Fill TInetNeighbourInfo struct based on this route.
       
  9340 
       
  9341 @param rinfo    struct to be filled by the neighbour information.
       
  9342 @param aRefTime reference time used in lifetime calculation. It should refer to the time
       
  9343                 the network interface has been up.
       
  9344 */
       
  9345     {
       
  9346     nginfo.iIndex = iIndex;
       
  9347     nginfo.iState = iState;
       
  9348     nginfo.iMetric = iMetric;
       
  9349     nginfo.iDstAddr = iPrefix;
       
  9350     nginfo.iInterface = iInterface.Index();
       
  9351     nginfo.iScopeId = iInterface.Scope((TScopeType)(iPrefix.Scope()-1));
       
  9352     nginfo.iHwAddr.Copy(iAddress.Address());
       
  9353 
       
  9354     if (iLifetime.iPreferred != KLifetimeForever)
       
  9355         {
       
  9356         nginfo.iLifetime = (iLifetime.iPreferred > aReftime) ?
       
  9357                 iLifetime.iPreferred - aReftime : 0;
       
  9358         }
       
  9359     else
       
  9360         {
       
  9361         nginfo.iLifetime = KLifetimeForever;
       
  9362         }
       
  9363     }
       
  9364     
       
  9365 
       
  9366 void CIp6Interface::SetAddressAndScope(TSockAddr &aAddr, const TSockAddr &aSrc) const
       
  9367     /**
       
  9368     * Assign an address (aSrc to aAddr) and supplement it with the
       
  9369     * scope information from the interface.
       
  9370     *
       
  9371     * @retval aAddr The address supplemented with the scope id.
       
  9372     * @param aSrc   The address to be supplemented.
       
  9373     *
       
  9374     * @note aSrc and aAddr can reference the same address.
       
  9375     */
       
  9376     {
       
  9377     // Allow call with aAddr == aSrc. Testing this may not be
       
  9378     // necessary, but just to be sure, avoid "overlapping"
       
  9379     // copy operation in such case... -- msa
       
  9380     if (&aAddr != &aSrc)
       
  9381         aAddr = aSrc;
       
  9382 
       
  9383     TInetAddr &addr = TInetAddr::Cast(aAddr);
       
  9384     if (addr.Family() == KAfInet)
       
  9385         addr.ConvertToV4Mapped();
       
  9386     if (addr.Family() == KAfInet6)
       
  9387         {
       
  9388         //
       
  9389         // Scope is stored only if the address family is KAfInet or KAfInet6,
       
  9390         // and if so, the final family is always KAfInet6.
       
  9391         const TUint scopeType = (TUint)(addr.Ip6Address().Scope() - 1);
       
  9392         if (scopeType > EScopeType_NET)
       
  9393             return;
       
  9394         addr.SetScope(iScope[scopeType]);
       
  9395         //
       
  9396         // (minor feature: if scope id would be 0, return IPv4 as KAfInet)
       
  9397         // [maybe of dubious value, just always return Ipv6 format?]
       
  9398         if (iScope[scopeType] == 0 && addr.IsV4Mapped())
       
  9399             addr.ConvertToV4();
       
  9400         }
       
  9401     }
       
  9402 
       
  9403 // CIp6Manager::InterfaceInfo
       
  9404 // **************************
       
  9405 /**
       
  9406 // Locate the next interface after aIndex and return the
       
  9407 // information and assigned interface index.
       
  9408 //
       
  9409 // @return
       
  9410 //  @li = 0, if no next interface exists
       
  9411 //  @li > 0, interface index, aInfo updated to describe this interface
       
  9412 */
       
  9413 TUint CIp6Manager::InterfaceInfo(TUint aIndex, TSoInetInterfaceInfo &aInfo) const
       
  9414     {
       
  9415     // ..yes, this is silly O(n!) (?) algorithm for scanning the interfaces. Each time
       
  9416     // this is called, it has find and count all entries that come before the specified
       
  9417     // aIndex.
       
  9418     // Also, if between calls, prefixes or id's have been added or removed, the algorithm
       
  9419     // fails and returns same entries multiple times or skips some that it should have
       
  9420     // returned. However, this should rarely happen.
       
  9421     TUint i = 0;
       
  9422     for (const CIp6Interface *iface = iInterfaceList;iface != NULL; iface = iface->iNext)
       
  9423         {
       
  9424         TInt found = 0;
       
  9425         for (const TIp6AddressInfo *address = &iface->iAddress; ; address = &address->iNext->iInfo)
       
  9426             {
       
  9427             TIp6Addr addr(KInet6AddrNone);
       
  9428             TInt length = 0;
       
  9429             // "i" represents a virtual index over all *assigned* addresses in all interfaces,
       
  9430             // with exception that at least one entry is returned for each interface, whether
       
  9431             // there is assigned addresses or not.
       
  9432             if (!address->IsSet())
       
  9433                 {
       
  9434                 if (address->iNext)
       
  9435                     continue;       // Check next address.
       
  9436                 //
       
  9437                 // This is the last address (actually, this is the primary address slot)
       
  9438                 //
       
  9439                 if (found > 0 || ++i <= aIndex)
       
  9440                     break;          // Done with this interface.
       
  9441                 // No entries returned from this interface,
       
  9442                 // return one dummy with no address
       
  9443                 }
       
  9444             else if (address->iPrefix == 0)
       
  9445                 {
       
  9446                 //
       
  9447                 // Specified individual alias address
       
  9448                 //
       
  9449                 ++found; 
       
  9450                 if (++i <= aIndex)  // Already processed?
       
  9451                     {
       
  9452                     if (address->iNext)
       
  9453                         continue;   // Look next address.
       
  9454                     else
       
  9455                         break;      // Last address, look for next interface
       
  9456                     }
       
  9457                 // Use address as is...
       
  9458                 addr = address->iId;
       
  9459                 }
       
  9460             else
       
  9461                 {
       
  9462                 //
       
  9463                 // Address is specified as autoconfigured ID part, find out the next
       
  9464                 // prefix to combine with it.
       
  9465                 //
       
  9466                 // coverity[write_write_order]
       
  9467                 const CIp6Route *route = route = iface->iRouteList;
       
  9468                 for (; route != NULL; route = route->iNext)
       
  9469                     {
       
  9470                     if (!route->IsMyPrefix())
       
  9471                         continue;
       
  9472                     // The lengths of the prefix and id must be compatible to be
       
  9473                     // combined.
       
  9474                     if (route->iLength != address->iPrefix)
       
  9475                         continue;
       
  9476 
       
  9477                     found++;
       
  9478                     if (++i > aIndex)
       
  9479                         break;  // a prefix found!
       
  9480                     // this prefix was already processed look forward...
       
  9481                     }
       
  9482                 if (route == NULL)
       
  9483                     {
       
  9484                     // No unprocessed prefixes, go to next address, if any
       
  9485                     if (address->iNext)
       
  9486                         continue;
       
  9487                     else
       
  9488                         {
       
  9489                         if (found > 0 || ++i <= aIndex)
       
  9490                             break;          // Done with this interface.
       
  9491                         // No entries returned from this interface,
       
  9492                         // return one dummy with no address (or whatever
       
  9493                         // the current address points to).
       
  9494                         addr = address->iId;
       
  9495                         }
       
  9496                     }
       
  9497                 else
       
  9498                     {
       
  9499                     //
       
  9500                     // Combine prefix and current id part into full address
       
  9501                     //
       
  9502                     addr = route->iPrefix;
       
  9503                     length = route->iLength;
       
  9504                     MakeFullAddress(addr, length, address->iId.u.iAddr8, sizeof(address->iId.u.iAddr8));
       
  9505                     }
       
  9506                 }
       
  9507             //
       
  9508             // "Interface" located, return information about it
       
  9509             //
       
  9510             aInfo.iName = iface->iName;
       
  9511             if (iface->iNifIf == NULL || !address->IsSet())
       
  9512                 aInfo.iState = EIfDown; // no interface or address not known or was duplicate
       
  9513             else if (iface->iState == EFlow_READY)
       
  9514                 aInfo.iState = EIfUp;
       
  9515             else if (iface->iState == EFlow_PENDING)
       
  9516                 aInfo.iState = EIfPending;
       
  9517             else if (iface->iState == EFlow_HOLD)
       
  9518                 aInfo.iState = EIfBusy;
       
  9519             else
       
  9520                 aInfo.iState = EIfDown;
       
  9521             aInfo.iTag = iface->iName;  // dubious, but what else? -- msa
       
  9522             aInfo.iMtu = iface->iSMtu;
       
  9523             aInfo.iSpeedMetric = iface->iSpeedMetric;
       
  9524             aInfo.iFeatures = iface->iFeatures;
       
  9525             aInfo.iHwAddr = iface->iHwAddr;
       
  9526 
       
  9527             iface->SetAddressAndScope(aInfo.iNameSer1, iface->iNameSer1);
       
  9528             iface->SetAddressAndScope(aInfo.iNameSer2, iface->iNameSer2);
       
  9529 
       
  9530             TInetAddr none;
       
  9531             if (addr.IsV4Mapped())
       
  9532                 {
       
  9533                 // IPv4 interface
       
  9534                 none.SetAddress(0);
       
  9535                 //
       
  9536                 // Get some configuration information
       
  9537                 // (ignore errors and assume the 'cfg' is
       
  9538                 // mostly initialized to null addresses in such case)
       
  9539                 //
       
  9540                 TPckgBuf<TSoInetIfConfig> cfg;
       
  9541                 (void)GetIp4Config(iface->iNifIf, cfg);
       
  9542                 const TSoInetIfConfig &cf = cfg();
       
  9543                 ((TInetAddr &)aInfo.iNetMask) = cf.iConfig.iNetMask;
       
  9544                 iface->SetAddressAndScope(aInfo.iBrdAddr, cf.iConfig.iBrdAddr);
       
  9545                 }
       
  9546             else
       
  9547                 {
       
  9548                 // IPv6 interface
       
  9549                 none.SetAddress(KInet6AddrNone);
       
  9550                 ((TInetAddr &)aInfo.iNetMask) = none;
       
  9551                 ((TInetAddr &)aInfo.iBrdAddr) = none;
       
  9552                 }
       
  9553 
       
  9554             // default gateway
       
  9555             TInetAddr gw;
       
  9556             iface->GetDefGateway(addr.IsV4Mapped(), gw);
       
  9557             iface->SetAddressAndScope(aInfo.iDefGate, gw);
       
  9558 
       
  9559             ((TInetAddr &)aInfo.iAddress) = none;
       
  9560             MagicSetAddress(aInfo.iAddress, addr, length, &aInfo.iNetMask);
       
  9561             iface->SetAddressAndScope(aInfo.iAddress, aInfo.iAddress);
       
  9562             return i;
       
  9563             }
       
  9564         }
       
  9565     return 0;
       
  9566     }
       
  9567 
       
  9568 
       
  9569 TInt CIp6Manager::GetInterfaces(TDes8& aOption) const
       
  9570     {
       
  9571     TOverlayArray<TInetInterfaceInfo> info(aOption);
       
  9572     TInt idx = 0, exceed = 0;
       
  9573     const CIp6Interface *iface = iInterfaceList;
       
  9574 
       
  9575     while (iface)
       
  9576         {
       
  9577         // IndexPtr returns NULL, if there is not enough room in descriptor
       
  9578         if (info.IndexPtr(idx))
       
  9579             {
       
  9580             TInetInterfaceInfo *const opt = new (info.IndexPtr(idx)) TInetInterfaceInfo;
       
  9581             opt->iIndex = iface->iScope[0];
       
  9582             opt->iName = iface->iName;
       
  9583             opt->iState = iface->iState;
       
  9584             opt->iSMtu = iface->iSMtu;
       
  9585             opt->iRMtu = iface->iRMtu;
       
  9586             opt->iSpeedMetric = iface->iSpeedMetric;
       
  9587             opt->iFeatures = iface->iFeatures;
       
  9588             opt->iHwAddr = iface->iHwAddr;
       
  9589 
       
  9590             idx++;
       
  9591             }
       
  9592         else
       
  9593             {
       
  9594             exceed++;
       
  9595             }
       
  9596         iface = iface->iNext;
       
  9597         }
       
  9598 
       
  9599     info.SetLength(idx);
       
  9600 
       
  9601     return exceed;
       
  9602     }
       
  9603 
       
  9604 
       
  9605 TInt CIp6Manager::GetAddresses(TDes8 &aOption) const
       
  9606     {
       
  9607     TOverlayArray<TInetAddressInfo> info(aOption);
       
  9608     TInt idx = 0, excess = 0, count = 0;
       
  9609     #ifdef _DEBUG
       
  9610         TInt ifaceSpecificAddrIdx = 0;
       
  9611     #endif
       
  9612 
       
  9613     for (const CIp6Interface *iface = iInterfaceList;iface != NULL; iface = iface->iNext)
       
  9614         {
       
  9615         #ifdef _DEBUG
       
  9616             ifaceSpecificAddrIdx = 0;
       
  9617         #endif
       
  9618         
       
  9619         TTime stamp;
       
  9620         stamp.UniversalTime();
       
  9621         const TLifetime current_time = iface->Elapsed(stamp);
       
  9622       
       
  9623         for (   const TIp6AddressInfo *address = &iface->iAddress;
       
  9624                 address != NULL;
       
  9625                 address = &address->iNext->iInfo)
       
  9626             {
       
  9627             TIp6Addr addr(KInet6AddrNone);
       
  9628 
       
  9629         // Own prefixes are appended with an ID part used for the interface and included in
       
  9630         // address list. They are stored in route table with "myprefix" flag.
       
  9631         // Route table is maintained separately for each interface, hence the multilevel loop
       
  9632             const CIp6Route *route = iface->iRouteList;
       
  9633             for (;;)
       
  9634                 {
       
  9635                 TBool haveprefix = EFalse;
       
  9636 
       
  9637                 if (route && !route->IsMyPrefix())
       
  9638                     {
       
  9639                     route = route->iNext;
       
  9640                     continue;
       
  9641                     }
       
  9642 
       
  9643                 // The lengths of the prefix and id must be compatible to be
       
  9644                 // combined.
       
  9645                 if (route && route->iLength != address->iPrefix)
       
  9646                     {
       
  9647                     route = route->iNext;
       
  9648                     continue;
       
  9649                     }
       
  9650             
       
  9651                 if (route == NULL || address->iPrefix == 0)
       
  9652                     {
       
  9653                     addr = address->iId;
       
  9654                     }
       
  9655                 else
       
  9656                     {
       
  9657                     // Combine prefix and current id part into full address
       
  9658                     addr = route->iPrefix;
       
  9659                     haveprefix = ETrue;
       
  9660                     MakeFullAddress(addr, route->iLength, address->iId.u.iAddr8, sizeof(address->iId.u.iAddr8));
       
  9661                     }
       
  9662 
       
  9663                 if (info.IndexPtr(idx))
       
  9664                     {
       
  9665                     #ifdef _DEBUG
       
  9666                         if( !address->iId.IsUnspecified() )
       
  9667                             {
       
  9668                             if( ifaceSpecificAddrIdx == 0 )
       
  9669                                 {
       
  9670                                 ASSERT( address->IsPrimary() );
       
  9671                                 }
       
  9672                             else
       
  9673                                 {
       
  9674                                 ASSERT( !address->IsPrimary() );
       
  9675                                 }
       
  9676                             }
       
  9677                     #endif
       
  9678                     
       
  9679                     TInetAddressInfo *const opt = new (info.IndexPtr(idx)) TInetAddressInfo;
       
  9680 
       
  9681                     opt->iInterface = iface->iScope[0];
       
  9682                     opt->iAddress = addr;
       
  9683                     opt->iPrefixLen = address->iPrefix;
       
  9684                     opt->iGenerations = address->iGenerated;
       
  9685                     opt->iNS = address->iNS;
       
  9686                     opt->iState = address->AddressState();
       
  9687                     opt->iType = address->AddressType();
       
  9688                     opt->iFlags = 0;
       
  9689 
       
  9690             // We distinct the "ID"-entries from "prefix" entries for the user.
       
  9691             // The actual set of usable addresses is the set of prefix x id combinations.
       
  9692             // This has more significance when handling address events rather than here,
       
  9693             // but I'd like to do it for completeness
       
  9694                     if (!haveprefix)
       
  9695                         {
       
  9696                         opt->iFlags |= TInetAddressInfo::EF_Id;
       
  9697                         }
       
  9698                     else
       
  9699                         {
       
  9700                         opt->iFlags |= TInetAddressInfo::EF_Prefix;
       
  9701                         }
       
  9702 
       
  9703                     TScopeType st = (TScopeType) (addr.Scope() - 1);
       
  9704                     opt->iScopeId = iface->Scope(st);
       
  9705 
       
  9706                     TLifetime plt = KLifetimeForever, vlt = KLifetimeForever;
       
  9707 
       
  9708                     // Lifetimes relate to the interface startup time
       
  9709                     if (haveprefix)
       
  9710                         {
       
  9711                         if (route->iLifetime.iPreferred != KLifetimeForever)
       
  9712                             {
       
  9713                             plt = (route->iLifetime.iPreferred > current_time) ?
       
  9714                                         route->iLifetime.iPreferred - current_time : 0;
       
  9715                             }
       
  9716                         if (route->iLifetime.iPreferred != KLifetimeForever &&
       
  9717                                     route->iLifetime.iStored != KLifetimeForever)
       
  9718                             {
       
  9719                             vlt = (route->iLifetime.iStored > current_time) ?
       
  9720                                         route->iLifetime.iStored - current_time : 0;
       
  9721                             }
       
  9722 
       
  9723                         if (route->iLifetime.iDeprecated)
       
  9724                             {
       
  9725                             opt->iFlags |= TInetAddressInfo::EF_Deprecated;
       
  9726                             }
       
  9727                         }
       
  9728                     else
       
  9729                         {
       
  9730                         // Address lifetimes are computed in timer units!
       
  9731                         const TLifetime current_age = ElapsedUnits(address->iCreated, stamp);
       
  9732 
       
  9733                         if (address->iPLT != KLifetimeForever)
       
  9734                             {
       
  9735                             plt = (address->iPLT > current_age) ?
       
  9736                                     address->iPLT - current_age : 0 /* 0 = expired*/;
       
  9737                             plt /= TIMER_UNIT;
       
  9738                             }
       
  9739             
       
  9740                         if (address->iVLT != KLifetimeForever)
       
  9741                             {
       
  9742                             vlt = (address->iVLT > current_age) ?
       
  9743                                         address->iVLT - current_age : 0 /* 0 = expired*/;
       
  9744                             vlt /= TIMER_UNIT;
       
  9745                             }
       
  9746                     
       
  9747                         if (plt == 0)
       
  9748                             {
       
  9749                             opt->iFlags |= TInetAddressInfo::EF_Deprecated;
       
  9750                             }
       
  9751                         }
       
  9752 
       
  9753                     opt->iPrefLifetime = plt;
       
  9754                     opt->iValidLifetime = vlt;
       
  9755                     count++;
       
  9756                     }
       
  9757                 else
       
  9758                     {
       
  9759                     excess++;
       
  9760                     }
       
  9761 
       
  9762                 idx++;
       
  9763                 if (!route) break;
       
  9764                 route = route->iNext;
       
  9765 
       
  9766                 // Must try one time with route == NULL to output a possible pure Id entry
       
  9767                 }
       
  9768 
       
  9769             if (!address->iNext)
       
  9770                 {
       
  9771                 break;
       
  9772                 }
       
  9773 
       
  9774             #ifdef _DEBUG
       
  9775                 ifaceSpecificAddrIdx++;
       
  9776             #endif
       
  9777             }
       
  9778         }
       
  9779 
       
  9780     info.SetLength(count);
       
  9781 
       
  9782     // Return number of addresses not fit into the option buffer. 0 indicates all of them are
       
  9783     // listed
       
  9784     return excess;
       
  9785     }
       
  9786 
       
  9787 
       
  9788 TInt CIp6Manager::GetRoutes(TDes8& aOption) const
       
  9789     {
       
  9790     TOverlayArray<TInetRouteInfo> info(aOption);
       
  9791     TInt idx = 0, exceed = 0;
       
  9792 
       
  9793     for (const CIp6Interface *iface = iInterfaceList; iface != NULL; iface = iface->iNext)
       
  9794         {
       
  9795         for (const CIp6Route *route = iface->iRouteList; route != NULL; route = route->iNext)
       
  9796             {
       
  9797             // Ignore myprefix entries, these are listed in GetAddresses()
       
  9798             if (route->IsMyPrefix())
       
  9799                 {
       
  9800                 continue;
       
  9801                 }
       
  9802         
       
  9803             if (idx < info.MaxLength())
       
  9804                 {
       
  9805                 TTime stamp;
       
  9806                 stamp.UniversalTime();
       
  9807                 TInetRouteInfo *const rinfo = new (info.IndexPtr(idx)) TInetRouteInfo;
       
  9808                 route->FillRouteInfo(*rinfo, iface->Elapsed(stamp));
       
  9809                 idx++;
       
  9810                 }
       
  9811             else
       
  9812                 {
       
  9813                 exceed++;
       
  9814                 }
       
  9815             }
       
  9816         }
       
  9817 
       
  9818     info.SetLength(idx);
       
  9819 
       
  9820     return exceed;
       
  9821     }
       
  9822 
       
  9823 
       
  9824 // CIp6Manager::RouteInfo
       
  9825 // **********************
       
  9826 /**
       
  9827 // Locate the next route after aIndex and return the
       
  9828 // information and assinged route index.
       
  9829 //
       
  9830 // @return
       
  9831 //  @li = 0, if not next route exits
       
  9832 //  @li > 0, route index, aInfo updated to describe this route
       
  9833 */
       
  9834 TUint CIp6Manager::RouteInfo(TUint aIndex, TSoInetRouteInfo &aInfo) const
       
  9835     {
       
  9836     const CIp6Route *rt = NULL;
       
  9837     const CIp6Interface *ifp;
       
  9838     for (ifp = iInterfaceList;; ifp = ifp->iNext)
       
  9839         {
       
  9840         if (ifp == NULL)
       
  9841             return 0;       // No more routes;
       
  9842 
       
  9843         for (rt = ifp->iRouteList; rt != NULL; rt = rt->iNext)
       
  9844             if (rt->iIndex > aIndex &&
       
  9845                 !rt->IsMyPrefix()) // ..additional condition: ingore "prefix" entries in the list!
       
  9846                 goto found_one;
       
  9847         }
       
  9848     // At least for now, the route list is *NOT* ordered by
       
  9849     // the index. Thus, need to find a next higher index by
       
  9850     // scanning the full list!
       
  9851 found_one:  // ifp != NULL && rt != NULL
       
  9852     const CIp6Route *next = rt;
       
  9853     for (;;)
       
  9854         {
       
  9855         for (;rt; rt = rt->iNext)
       
  9856             {
       
  9857             if (rt->iIndex > aIndex && rt->iIndex < next->iIndex &&
       
  9858                 !rt->IsMyPrefix()) // ..additional condition: ingore "prefix" entries in the list!
       
  9859                 next = rt;
       
  9860             }
       
  9861         if ((ifp = ifp->iNext) == NULL)
       
  9862             break;
       
  9863         rt = ifp->iRouteList;
       
  9864         }
       
  9865 
       
  9866     TIp6Addr ifaddr(KInet6AddrNone);
       
  9867 
       
  9868     // The existing values of TRouteState and TRouteType are not
       
  9869     // quite suitable for the current IPv6 Neighbor Discovery
       
  9870     // environment. Just do some reasonable effort in mapping
       
  9871     // the route state into iState & iType.
       
  9872     //
       
  9873     // - if route is controlled by ND, set type = ERtIcmpAdd
       
  9874     //
       
  9875     aInfo.iType = ERtNormal;
       
  9876     aInfo.iState = ERtReady;
       
  9877     switch (next->iState)
       
  9878         {
       
  9879         case CIp6Route::EIncomplete:
       
  9880             aInfo.iType = ERtIcmpAdd;
       
  9881             aInfo.iState = ERtPending;
       
  9882             break;
       
  9883         case CIp6Route::EReachable:
       
  9884         case CIp6Route::EStale:
       
  9885         case CIp6Route::EDelay:
       
  9886         case CIp6Route::EProbe:
       
  9887             aInfo.iType = ERtIcmpAdd;
       
  9888             aInfo.iState = ERtReady;
       
  9889             break;
       
  9890         default:
       
  9891             break;
       
  9892         }
       
  9893     aInfo.iMetric = next->iMetric;
       
  9894 
       
  9895     (void)next->iInterface.SelectSource(ifaddr, next->iPrefix);
       
  9896 
       
  9897     MagicSetAddress(aInfo.iIfAddr, ifaddr, 0);
       
  9898     next->iInterface.SetAddressAndScope(aInfo.iIfAddr, aInfo.iIfAddr);
       
  9899     if (next->iState == CIp6Route::ELoopback)
       
  9900         aInfo.iGateway.SetFamily(0);
       
  9901     else
       
  9902         {
       
  9903         next->iAddress.GetAddress(aInfo.iGateway);
       
  9904         next->iInterface.SetAddressAndScope(aInfo.iGateway, aInfo.iGateway);
       
  9905         }
       
  9906     MagicSetAddress(aInfo.iDstAddr, next->iPrefix, next->iLength, &aInfo.iNetMask);
       
  9907     return next->iIndex;
       
  9908     }
       
  9909 
       
  9910 // CIp6Manager::InterfaceQueryOption
       
  9911 // *********************************
       
  9912 // Get information about interface
       
  9913 //
       
  9914 TInt CIp6Manager::InterfaceQueryOption(TUint aName, TSoInetIfQuery &aQuery, const TInt aLength) const
       
  9915     {
       
  9916     // aLength holds the availabe space for iZone[] array (backward compatibility kludge for
       
  9917     // some odd applications that might be using old in_sock.h without the iZone part!
       
  9918     if (aLength < 0)
       
  9919         return KErrArgument;    // Option is too short to be anything sensible!
       
  9920 
       
  9921     const CIp6Interface *iface = NULL;
       
  9922 
       
  9923     //
       
  9924     // the destination address is required in Ip6 format
       
  9925     // in processing, prefetch...
       
  9926     //
       
  9927     TIp46Addr dst(aQuery.iDstAddr);
       
  9928     //
       
  9929     // The aName determines how the interface is to be located
       
  9930     //
       
  9931     switch (aName)
       
  9932         {
       
  9933         case KSoInetIfQueryByDstAddr:
       
  9934             {
       
  9935             //
       
  9936             // *NOTE* This is not satisfactory! It will not give the right answer,
       
  9937             // if there are hooks that might change the interface based on destination
       
  9938             // address (or some policy). ...and if policies (IPSEC, QoS) come into
       
  9939             // picture, we need to have the protocol and port here too!
       
  9940             // To solve, need almost to create a flow and connect it, but not
       
  9941             // refresh (no ReadyL() phase, nor interface Activation!)
       
  9942             //
       
  9943             const CIp6Route *const route = FindRoute(dst,
       
  9944                 aQuery.iDstAddr.Scope(), (TUint)(aQuery.iDstAddr.Ip6Address().Scope()-1));
       
  9945             if (route)
       
  9946                 iface = &route->iInterface;
       
  9947             break;
       
  9948             }
       
  9949         case KSoInetIfQueryBySrcAddr:
       
  9950             iface = FindInterface(aQuery.iSrcAddr);
       
  9951             break;
       
  9952         case KSoInetIfQueryByIndex:
       
  9953             iface = FindInterface(aQuery.iIndex);
       
  9954             break;
       
  9955         case KSoInetIfQueryByName:
       
  9956             iface = FindInterface(aQuery.iName);
       
  9957             break;
       
  9958         default:
       
  9959             return KErrNotSupported;
       
  9960         }
       
  9961     if (iface == NULL)
       
  9962         return KErrNotFound;
       
  9963     //
       
  9964     // Fill In the query information
       
  9965     //
       
  9966     // Try to select src address based on whatever content of dst has. If
       
  9967     // fails, then src address will be unspecified.
       
  9968     if (iface->SelectSource(dst, dst) != NULL)
       
  9969         aQuery.iSrcAddr.SetAddress(dst);
       
  9970     else
       
  9971         aQuery.iSrcAddr.Init(0);
       
  9972     // Zone ids, copy as much as there is available space in option.
       
  9973     const TInt N = (aLength > (TInt)sizeof(iface->iScope) ? sizeof(iface->iScope) : aLength) / sizeof(aQuery.iZone[0]);
       
  9974     for (int i = 0; i < N; ++i)
       
  9975         aQuery.iZone[i] = iface->iScope[i];
       
  9976     aQuery.iIndex = iface->iScope[0];       // make sure iIndex is also correct.
       
  9977     aQuery.iName = iface->iName;            // Interface Name
       
  9978     aQuery.iIsUp = iface->iNifIf != NULL;   // 1 = if interface has CNifIfBase * attached
       
  9979     return KErrNone;
       
  9980     }
       
  9981 
       
  9982 // CIp6Manager::InetInterfaceOption
       
  9983 // ********************************
       
  9984 // Modify Inet Interface information (SetOption part)
       
  9985 //
       
  9986 TInt CIp6Manager::InetInterfaceOption(TUint aName, const TSoInet6InterfaceInfo &aInfo)
       
  9987     {
       
  9988     #ifdef _LOG
       
  9989         TBuf<39> addressStr;
       
  9990         aInfo.iAddress.Output( addressStr );
       
  9991         TBuf<39> netMaskStr;
       
  9992         aInfo.iNetMask.Output( netMaskStr );
       
  9993         TBuf<39> brdAddrStr;
       
  9994         aInfo.iBrdAddr.Output( brdAddrStr );
       
  9995         TBuf<39> defGateStr;
       
  9996         aInfo.iDefGate.Output( defGateStr );
       
  9997         TBuf<39> nameSer1Str;
       
  9998         aInfo.iNameSer1.Output( nameSer1Str );
       
  9999         TBuf<39> nameSer2Str;
       
 10000         aInfo.iNameSer2.Output( nameSer2Str );
       
 10001 
       
 10002         LOG( Log::Printf( _L( "CIp6Interface::InetInterfaceOption iName(%S), iState(%d), iMtu(%d), iSpeedMetric(%d), iFeatures(%u), iAddress(%S), iNetMask(%S), iBrdAddr(%S), iDefGate(%S), iNameSer1(%S), iNameSer2(%S), iDelete(%u), iAlias(%u), iDoPrefix(%u), iDoId(%u), iDoState(%u), iDoAnycast(%u), iDoProxy(%u)" ),
       
 10003             &aInfo.iName,
       
 10004             aInfo.iState,
       
 10005             aInfo.iMtu,
       
 10006             aInfo.iSpeedMetric,
       
 10007             aInfo.iFeatures,
       
 10008             &addressStr,
       
 10009             &netMaskStr,
       
 10010             &brdAddrStr,
       
 10011             &defGateStr,
       
 10012             &nameSer1Str,
       
 10013             &nameSer2Str,
       
 10014             aInfo.iDelete,
       
 10015             aInfo.iAlias,
       
 10016             aInfo.iDoPrefix,
       
 10017             aInfo.iDoId,
       
 10018             aInfo.iDoAnycast,
       
 10019             aInfo.iDoProxy
       
 10020         ) );
       
 10021     #endif
       
 10022 
       
 10023     // Locate the interface
       
 10024     CIp6Interface *iface = FindInterface(aInfo.iName);
       
 10025     if (iface)
       
 10026         {
       
 10027         switch (aName)
       
 10028             {
       
 10029             case KSoInetDeleteInterface:
       
 10030                 RemoveInterface(iface);
       
 10031                 return KErrNone;
       
 10032             case KSoInetConfigInterface:
       
 10033             case KSoInetChangeInterface:
       
 10034                 break;
       
 10035             case KSoInetResetInterface:
       
 10036                 // *THIS IMPLEMENATION NEEDS TO BE LOOKED INTO*  -- msa
       
 10037                 {
       
 10038                 LOG(Log::Printf(_L("CIp6Manager::InetInterfaceOption(KSoInetResetInterface, %S)"), &iface->iName));
       
 10039                 if (iface->iState >= EFlow_READY)
       
 10040                     iface->iState = EFlow_HOLD;
       
 10041 
       
 10042                 for(CIp6Route *rt=iface->iRouteList; rt != NULL; rt = rt->iNext)
       
 10043                     MoveToHolding(*rt);
       
 10044                 iface->Reset(1);        // Reset to initial state, but keep binding to NIF
       
 10045                 }
       
 10046                 return KErrNone;
       
 10047             case KSoInetStartInterface:
       
 10048                 // *THIS IMPLEMENATION NEEDS TO BE LOOKED INTO*  -- msa
       
 10049                 LOG(Log::Printf(_L("CIp6Manager::InetInterfaceOption(KSoInetStartInterface, %S)"), &iface->iName));
       
 10050                 StartSending(iface->iNifIf);
       
 10051                 return KErrNone;
       
 10052             case KSoInetCreateIPv4LLOnInterface:
       
 10053                 {
       
 10054                 LOG(Log::Printf(_L("CIp6Manager::InetInterfaceOption(KSoInetCreateIPv4LLOnInterface, %S)"), &iface->iName));
       
 10055                 
       
 10056                 TInt err = KErrNone;
       
 10057                 const TInt flag = iface->HaveIp4LinkLocal();
       
 10058 
       
 10059                 if( flag == CIp6Interface::EV4LLConfigDaemonControlled )
       
 10060                     {
       
 10061                     // Check for any state change.
       
 10062                     if (aInfo.iDoState)
       
 10063                         {
       
 10064                         if (aInfo.iState == EIfDown)
       
 10065                             iface->iState = KErrNotReady;
       
 10066                         else if (aInfo.iState == EIfUp)
       
 10067                             iface->iState = EFlow_READY;
       
 10068                         else
       
 10069                             err = KErrArgument; // no others supported now!
       
 10070                         }
       
 10071 
       
 10072                     if( err == KErrNone )
       
 10073                         {
       
 10074                         // Try to create a link local.
       
 10075                         TInt retVal = iface->ConfigureLinkLocal( 0 );
       
 10076                         
       
 10077                         // Check for any errors.
       
 10078                         if( retVal == 1 )
       
 10079                             {
       
 10080                             // Link local was created.
       
 10081                             err = KErrNone;
       
 10082 
       
 10083                             // Address configuration has been changed, the process completes
       
 10084                             // through the Timeout function, activate it.
       
 10085                             TTime stamp;
       
 10086                             stamp.UniversalTime();
       
 10087                             iface->Timeout(stamp);
       
 10088                             }
       
 10089                         else
       
 10090                             {
       
 10091                             if( iface->HasIpv4LinkLocalAddr() )
       
 10092                                 {
       
 10093                                 // Link local already exists.
       
 10094                                 err = KErrNone;
       
 10095                                 }
       
 10096                             else if( !iface->iIsIPv4 )
       
 10097                                 {
       
 10098                                 // This interface option is only available when using IPv4.
       
 10099                                 err = KErrNotSupported;
       
 10100                                 }
       
 10101                             else
       
 10102                                 {
       
 10103                                 // Link local could not be created for unknown reasons.
       
 10104                                 err = KErrUnknown;
       
 10105                                 }
       
 10106                             }
       
 10107                         }
       
 10108                     }
       
 10109                 else
       
 10110                     {
       
 10111                     // This interface option is only available when EV4LLConfigDaemonControlled is specified.
       
 10112                     err = KErrNotSupported;
       
 10113                     }
       
 10114                 
       
 10115                 return err;
       
 10116                 }
       
 10117             default:
       
 10118                 return KErrNotSupported;
       
 10119             }
       
 10120         }
       
 10121     else if (aName == STATIC_CAST(TUint,KSoInetConfigInterface))
       
 10122         {
       
 10123         TRAPD(err, iface = GetInterfaceByNameL(aInfo.iName));
       
 10124         if (iface == NULL)
       
 10125             return err;
       
 10126         // For a newly created interface, let the address decide the "mode"
       
 10127         if (aInfo.iAddress.Family() == KAfInet6)
       
 10128             iface->iNifUser = iNifUser[E_IPv6];
       
 10129         }
       
 10130     else
       
 10131         return KErrNotFound;
       
 10132 
       
 10133     // Execute the option on interface
       
 10134 
       
 10135     TIp6Addr addr;
       
 10136     TInt prefix = MagicGetAddress(addr, aInfo.iAddress, aInfo.iNetMask);
       
 10137     if (prefix < 0)
       
 10138         return prefix;  // Bad address information
       
 10139     if (aInfo.iMtu > 0)
       
 10140         iface->iSMtu = iface->iRMtu = iface->iPMtu = aInfo.iMtu;
       
 10141     if (aInfo.iSpeedMetric > 0)
       
 10142         iface->iSpeedMetric = aInfo.iSpeedMetric;
       
 10143     if (aInfo.iDoState)
       
 10144         {
       
 10145         if (aInfo.iState == EIfDown)
       
 10146             iface->iState = KErrNotReady;
       
 10147         else if (aInfo.iState == EIfUp)
       
 10148             iface->iState = EFlow_READY;
       
 10149         else
       
 10150             return KErrArgument;    // no others supported now!
       
 10151         }
       
 10152     iface->UpdateNameServers(aInfo.iNameSer1, aInfo.iNameSer2, 1); // Note, override mode!
       
 10153 
       
 10154     //
       
 10155     // Do some iDefGate processing (if specified)
       
 10156     //
       
 10157     if (!aInfo.iDefGate.IsUnspecified())
       
 10158         {
       
 10159         // Family is either KAfInet or KAfInet6 now
       
 10160         TInetAddr defgate(aInfo.iDefGate);
       
 10161         if (defgate.Family() == KAfInet)
       
 10162             defgate.ConvertToV4Mapped();
       
 10163 
       
 10164         static const TLifetime zero = 0;
       
 10165         const TLifetime *const lifetime = aInfo.iDelete ? &zero : NULL;
       
 10166         const TInt pb = defgate.IsV4Mapped() ? 96 : 0;
       
 10167         const TIp6Addr &gw = defgate.Ip6Address();
       
 10168         if (gw.IsEqual(addr))
       
 10169             (void)iface->GetRoute(gw, pb, KRouteAdd_ONLINK, NULL, lifetime);
       
 10170         else
       
 10171             {
       
 10172             (void)iface->GetRoute(gw, 128, KRouteAdd_ISROUTER, NULL, lifetime); 
       
 10173             (void)iface->GetRoute(gw, pb, KRouteAdd_GATEWAY, &defgate, lifetime);
       
 10174             }
       
 10175         }
       
 10176 
       
 10177     if (prefix > 128)
       
 10178         return KErrNone;    // No address info, ignore rest
       
 10179 
       
 10180     //
       
 10181     // prefix = 0 => request to configure a single address
       
 10182     // prefix > 0 => request to configure prefix and/or id part
       
 10183     //
       
 10184     if (aInfo.iDoId)
       
 10185         {
       
 10186         if (TIp46Addr::Cast(addr).IsMulticast())
       
 10187             {
       
 10188 #if 0
       
 10189             return KErrArgument;        // Cannot configure multicast address as own address
       
 10190 #else
       
 10191             //
       
 10192             // Experimental hack -- treat multicast address configuration as
       
 10193             // multicast join/leave group event
       
 10194             //
       
 10195             return iface->UpdateMulticast(addr,  aInfo.iDelete ? 0 : KLifetimeForever);
       
 10196 #endif
       
 10197             }
       
 10198 
       
 10199         // *NOTE* Some obscure stuff: You cannot configure a plain
       
 10200         // id, because this 'addr' is stored as is into the id list
       
 10201         // and the full address is used for DAD processing.
       
 10202         if (aInfo.iDelete)
       
 10203             {
       
 10204             const TInt err = iface->RemId(iface->GetId(addr));
       
 10205             if (err != KErrNone)
       
 10206                 return err;
       
 10207             }
       
 10208         else if (aInfo.iDoAnycast || aInfo.iDoProxy)
       
 10209             {
       
 10210             //
       
 10211             // Special addresses
       
 10212             //
       
 10213             const TInt address_type =
       
 10214                 aInfo.iDoAnycast ? TIp6AddressInfo::EAnycast :
       
 10215                 aInfo.iDoProxy ? TIp6AddressInfo::EProxy :
       
 10216                 TIp6AddressInfo::ENormal;
       
 10217             (void)iface->AddId(addr, 0, address_type);
       
 10218             prefix = 0; // "disarm" iDoPrefix processing below (not relevant for proxy/anycast)
       
 10219             }
       
 10220         else if (addr.IsV4Mapped())
       
 10221             {
       
 10222             // Configuring IPv4 interface with (prefix > 96) or without (prefix == 0)
       
 10223             // netmask. The "id" processing is adding the recognition of the network broadcast
       
 10224             // address. For IPv4, "alias" is always assumed implicitly
       
 10225             iface->ConfigureAddress(addr, prefix, ETrue);
       
 10226             prefix = 0; // "disarm" iDoPrefix processing below (not relevant for IPv4!)
       
 10227             }
       
 10228         else if (aInfo.iAlias || prefix == 0)
       
 10229             {
       
 10230             // when prefix==0, the request does not specify mask. Treat
       
 10231             // this as a request to add a special 128bit address as id
       
 10232             // (= configuring single address for interface). Do it
       
 10233             // always as "alias".
       
 10234             (void)iface->AddId(addr, prefix);
       
 10235             }
       
 10236         else
       
 10237             {
       
 10238             // Change/Define primary id part
       
 10239             iface->SetId(iface->iAddress, addr, prefix, TIp6AddressInfo::ENormal);
       
 10240             }
       
 10241         //
       
 10242         // Update lifetime and DAD events
       
 10243         //
       
 10244         TTime stamp;
       
 10245         stamp.UniversalTime();
       
 10246         iface->Timeout(stamp);
       
 10247         }
       
 10248     // If prefix=0, AddId already does SetPrefix...
       
 10249     if (aInfo.iDoPrefix && prefix > 0)
       
 10250         {
       
 10251         // ...works as if RA prefix option with A=1
       
 10252         const TLifetime lifetime = aInfo.iDelete ? 0 : KLifetimeForever;
       
 10253         iface->SetPrefix(addr, prefix, 1, lifetime);
       
 10254         // ...works as if RA prefix option with L=1
       
 10255         iface->GetRoute(addr, prefix, KRouteAdd_ONLINK, NULL, &lifetime);
       
 10256         }
       
 10257     return KErrNone;
       
 10258     }
       
 10259 
       
 10260 //
       
 10261 // CIpManager::InterfaceOption
       
 10262 // ***************************
       
 10263 /**
       
 10264 // This method implements *BOTH* SetOption and GetOption when level KSOLInterface
       
 10265 // The call is translated to a Control(). Somewhat dubious, but thats the way it
       
 10266 // was before...
       
 10267 */
       
 10268 TInt CIp6Manager::InterfaceOption(TUint aLevel, TUint aName, TDes8 &aOption) const
       
 10269     {
       
 10270     // Note: Checking against MaxLength only to be sure that the iName field
       
 10271     // of TSoIfInfo is accessible. It just blindly assumed that the caller
       
 10272     // has initialized the content properly (even if Length() is not necessarily
       
 10273     // correctly set). [To be compatible with the old implementation].
       
 10274     if ((TUint)aOption.MaxLength() < sizeof(TSoIfInfo))
       
 10275         return KErrArgument;    // Both Get/Set need the interface name!
       
 10276     const TSoIfInfo &opt = *(TSoIfInfo *)aOption.Ptr();
       
 10277 
       
 10278     // Locate Interface mathing the specified name
       
 10279     const CIp6Interface *const iface = FindInterface(opt.iName);
       
 10280     if (iface)
       
 10281         return iface->iNifIf ? iface->iNifIf->Control(aLevel, aName, aOption) : KErrNotReady;
       
 10282     // No such interface
       
 10283     return KErrBadDriver;
       
 10284     }
       
 10285 
       
 10286 
       
 10287 
       
 10288 //
       
 10289 // CIp6Manager::MulticastOption
       
 10290 // ****************************
       
 10291 // Process Multicast Options Join and Leave Group
       
 10292 //
       
 10293 TInt CIp6Manager::MulticastOption(TUint aName, const TIp6Mreq &aRequest)
       
 10294     {
       
 10295     if (!TIp46Addr::Cast(aRequest.iAddr).IsMulticast())
       
 10296         return KErrArgument;    // This must be a valid multicast address!
       
 10297     CIp6Route *route;
       
 10298     //
       
 10299     // Locate interface to be used
       
 10300     //
       
 10301     CIp6Interface *iface;
       
 10302     if (aRequest.iInterface == 0)
       
 10303         {
       
 10304         route = FindRoute(aRequest.iAddr, 0, 0);
       
 10305         if (route == NULL)
       
 10306             return KErrNotFound;
       
 10307         iface = &route->iInterface;
       
 10308         }
       
 10309     else
       
 10310         {
       
 10311         // Assuming the request.iInterface is always a true interface index.
       
 10312         // (and not a scope id depending on the scope of the multicast address)
       
 10313         iface = FindInterface(aRequest.iInterface);
       
 10314         if (iface == NULL || (iface->FindRoute(aRequest.iAddr, NULL)) == NULL)
       
 10315             {
       
 10316             // Should return something specific: "no multicast enabled interface" or something...
       
 10317             // or, should this cause dialup popup? -- msa
       
 10318             return KErrNotFound;
       
 10319             }
       
 10320         }
       
 10321     // Note: the caller must have already verified that aName is either KSoIp6JoinGroup or KSoIp6LeaveGroup
       
 10322     return iface->UpdateMulticast(aRequest.iAddr, aName == KSoIp6JoinGroup ? KLifetimeForever : 0);
       
 10323     }
       
 10324 
       
 10325 //
       
 10326 // CIp6Manager::GetOption
       
 10327 // **********************
       
 10328 TInt CIp6Manager::GetOption(TUint aLevel, TUint aName, TDes8 &aOption) const
       
 10329     {
       
 10330     return GetOption(aLevel, aName, aOption, *(CIp6Manager *)this);
       
 10331     }
       
 10332 
       
 10333 TInt CIp6Manager::GetOption(TUint aLevel, TUint aName, TDes8 &aOption, MProvdSecurityChecker &aChecker) const
       
 10334     {
       
 10335     if (aLevel == KSOLInterface)
       
 10336         {
       
 10337         const TInt ret = aChecker.CheckPolicy(KPolicyNetworkControl, 0);
       
 10338         if (ret != KErrNone)
       
 10339             return ret;
       
 10340         return InterfaceOption(aLevel, aName, aOption);
       
 10341         }
       
 10342 
       
 10343     else if (aLevel == KSolInetIfQuery)
       
 10344         {
       
 10345         // Returns an array of TInetInterfaceInfo objects
       
 10346         if (aName == KSoInetInterfaceInfo)
       
 10347             {
       
 10348             return GetInterfaces(aOption);
       
 10349             }
       
 10350 
       
 10351         // Returns an array of TInetAddressInfo objects
       
 10352         else if (aName == KSoInetAddressInfo)
       
 10353             {
       
 10354             return GetAddresses(aOption);
       
 10355             }
       
 10356 
       
 10357         // Returns an array of TInetRouteInfo objects
       
 10358         else if (aName == KSoInetRouteInfo)
       
 10359             {
       
 10360             return GetRoutes(aOption);
       
 10361             }
       
 10362 
       
 10363         // Other options return TSoInetIfQuery object
       
 10364         return InterfaceQueryOption(aName, *(TSoInetIfQuery *)aOption.Ptr(), aOption.Length() - _FOFF(TSoInetIfQuery, iZone[0]));
       
 10365         }
       
 10366     return KErrNotSupported;    // No get options supported for now (here)
       
 10367     }
       
 10368 
       
 10369 // CIp6Manager::SetOption
       
 10370 // **********************
       
 10371 TInt CIp6Manager::SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption)
       
 10372     {
       
 10373     return SetOption(aLevel, aName, aOption, *this);
       
 10374     }
       
 10375 
       
 10376 TInt CIp6Manager::SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption, MProvdSecurityChecker &aChecker)
       
 10377     {
       
 10378     const TUint8 &ref = *aOption.Ptr(); // Prefetch for use in below.
       
 10379 
       
 10380     if (aLevel == KSolInetIp)
       
 10381         {
       
 10382         if (aName == KSoIp6JoinGroup || aName == KSoIp6LeaveGroup)
       
 10383             {
       
 10384             if (aOption.Length() != sizeof(TIp6Mreq))
       
 10385                 return KErrArgument;
       
 10386             return MulticastOption(aName, (TIp6Mreq &)ref);
       
 10387             }
       
 10388         return KErrNotSupported;
       
 10389         }
       
 10390 
       
 10391     if (aLevel == KSolInetIfCtrl)
       
 10392         {
       
 10393         const TInt ret = aChecker.CheckPolicy(KPolicyNetworkControl, 0);
       
 10394         if (ret != KErrNone)
       
 10395             return ret;
       
 10396         if (aName == KSoIpv4LinkLocal &&
       
 10397                 aOption.Length() == sizeof(TSoInetIpv4LinkLocalInfo))
       
 10398             return SetIpv4LinkLocalOption((TSoInetIpv4LinkLocalInfo &)ref);
       
 10399         
       
 10400         if (aOption.Length() != sizeof(TSoInet6InterfaceInfo))
       
 10401             return KErrArgument;
       
 10402         return InetInterfaceOption(aName, (TSoInet6InterfaceInfo &)ref);
       
 10403         }
       
 10404     else if (aLevel == KSOLInterface)
       
 10405         {
       
 10406         const TInt ret = aChecker.CheckPolicy(KPolicyNetworkControl, 0);
       
 10407         if (ret != KErrNone)
       
 10408             return ret;
       
 10409         // InterfaceOption needs modifiable descriptor, make it so!
       
 10410         TPtr8 tmp((TUint8 *)&ref, aOption.Length());
       
 10411         return InterfaceOption(aLevel, aName, tmp);
       
 10412         }
       
 10413     else if (aLevel == KSolInetIfQuery)
       
 10414         {
       
 10415         const TInt ret = aChecker.CheckPolicy(KPolicyNetworkControl, 0);
       
 10416         if (ret != KErrNone)
       
 10417             return ret;
       
 10418         if (aOption.Length() != sizeof(TSoInetIfQuery))
       
 10419             return KErrArgument;
       
 10420         const TSoInetIfQuery &info = (TSoInetIfQuery &)ref;
       
 10421 
       
 10422         // Search interface by index and hand some special options.
       
 10423         // [These are not really very natural for KSolInetIfQuery
       
 10424         // and probably should be placed under some other level]
       
 10425         CIp6Interface *const iface = FindInterface(info.iIndex);
       
 10426         if (iface == NULL)
       
 10427             return KErrNotFound;
       
 10428         switch (aName)
       
 10429             {
       
 10430             // Copy the zone id vector from option to the interface.
       
 10431             case KSoInetIfQuerySetScope:
       
 10432                 {
       
 10433                 TUint loopCount = sizeof(iface->iScope) / sizeof(iface->iScope[0]);
       
 10434                 for (TUint i = 1; i < loopCount; ++i)
       
 10435                     iface->iScope[i] = info.iZone[i];
       
 10436                 iface->NotifyInterfaceEvent(EventTypeModify);
       
 10437                 return KErrNone;
       
 10438                 }
       
 10439             // Clear "IS ROUTER" flag on interface (IPv6 Neighbour Advertisement IS_ROUTER flag)
       
 10440             case KSoInetIfQuerySetHost:
       
 10441                 iface->iIsRouter = 0;
       
 10442                 return KErrNone;
       
 10443             // Set "IS ROUTER" flag on interface (IPv6 Neighbour Advertisement IS_ROUTER flag)
       
 10444             case KSoInetIfQuerySetRouter:
       
 10445                 iface->iIsRouter = 1;
       
 10446                 return KErrNone;
       
 10447             default:
       
 10448                 return KErrNotSupported;
       
 10449             }
       
 10450         }
       
 10451     else if (aLevel == KSolInetRtCtrl)
       
 10452         {
       
 10453         const TInt ret = aChecker.CheckPolicy(KPolicyNetworkControl, 0);
       
 10454         if (ret != KErrNone)
       
 10455             return ret;
       
 10456         if (aOption.Length() != sizeof(TSoInetRouteInfo))
       
 10457             return KErrArgument;
       
 10458 
       
 10459         const TSoInetRouteInfo& opt = (TSoInetRouteInfo &)ref;
       
 10460         TInetAddr gateway(opt.iGateway);
       
 10461         if (gateway.Family() == KAfInet)
       
 10462             gateway.ConvertToV4Mapped();
       
 10463 
       
 10464         // Because the iType of the TSoInetRouteInfo does not match very well
       
 10465         // with the internal route types, some "guesswork" is required to decide
       
 10466         // which type of route operated:
       
 10467         //
       
 10468         // The KSoInetRtCtrl supports the following:
       
 10469         // 1) Neighbor Cache entry, if iType == ERtIcmpAdd (prefix should be 128 bits!),
       
 10470         // 2) Gateway route, if iGateway was an IPv4 or IPv6 address (0 <= prefix <= 128)
       
 10471         // 3) Otherwise, Onlink route (0 <= prefix <= 128)
       
 10472         //
       
 10473         // For neighbor cache entry, the gateway address is the link layer address.
       
 10474         //
       
 10475         TUint rtype =
       
 10476             opt.iType == ERtIcmpAdd ? KRouteAdd_NEIGHBOR :
       
 10477             gateway.Family() == KAfInet6 ? KRouteAdd_GATEWAY : KRouteAdd_ONLINK;
       
 10478 
       
 10479         //
       
 10480         // Is interface specified by iIfAddr or iGateway?
       
 10481         //
       
 10482         CIp6Interface *iface = NULL;
       
 10483         if (opt.iIfAddr.Family() != KAFUnspec)
       
 10484             {
       
 10485             //
       
 10486             // Select interface by iIfAddr (IPv4 or IPv6 address)
       
 10487             //
       
 10488             iface = FindInterface(opt.iIfAddr);
       
 10489             }
       
 10490         else if (rtype == KRouteAdd_GATEWAY)
       
 10491             {
       
 10492             // Select interface by iGateway address
       
 10493             const CIp6Route *const rt = FindRoute(gateway.Ip6Address(), gateway.Scope(),
       
 10494                 (TUint)(gateway.Ip6Address().Scope()-1));
       
 10495             if (rt != NULL)
       
 10496                 iface = &rt->iInterface;
       
 10497             }
       
 10498         // Must have interface...
       
 10499         if (iface == NULL)
       
 10500             return KErrNotFound;
       
 10501 
       
 10502         //
       
 10503         // Convert iDstAddr/iNetMask into prefix
       
 10504         //
       
 10505         TIp6Addr prefix_addr;
       
 10506         const TInt prefix_len = MagicGetAddress(prefix_addr, opt.iDstAddr, opt.iNetMask);
       
 10507         if (prefix_len < 0 || prefix_len > 128)
       
 10508             return KErrArgument;        // Add ROUTE makes no sense without a valid prefix info!
       
 10509 
       
 10510         switch (aName)
       
 10511             {
       
 10512             case KSoInetDeleteRoute:
       
 10513                 rtype |= KRouteAdd_UPDATEONLY;
       
 10514                 break;
       
 10515             case KSoInetChangeRoute:
       
 10516                 rtype |= KRouteAdd_UPDATEONLY;
       
 10517                 /* FALLTRHOUGH */
       
 10518             case KSoInetAddRoute:
       
 10519                 // If this is adding/changing a gateway route, add also IS ROUTER status for the gateway!
       
 10520                 if ((rtype & KRouteAdd_TYPEMASK) == KRouteAdd_GATEWAY)
       
 10521                     {
       
 10522                     TIp6Addr src;
       
 10523                     CIp6Route *const n = iface->GetRoute(gateway.Ip6Address(), 128, KRouteAdd_ISROUTER);
       
 10524                     if (n && n->iState == CIp6Route::EIncomplete)
       
 10525                         if (iface->SelectSource(src,n->iPrefix)!=NULL) 
       
 10526                             n->StartND(src); 
       
 10527                         else 
       
 10528                             n->StartND(n->iInterface.iAddress.iId);
       
 10529                     }
       
 10530                 break;
       
 10531             default:
       
 10532                 return KErrNotSupported;
       
 10533             }
       
 10534 
       
 10535         CIp6Route *const route = iface->GetRoute(prefix_addr, prefix_len, rtype, &gateway);
       
 10536         if (route == NULL)
       
 10537             return (rtype & KRouteAdd_UPDATEONLY) != 0 ? KErrNotFound : KErrNoMemory;
       
 10538 
       
 10539         if (aName == STATIC_CAST(TUint,KSoInetDeleteRoute))
       
 10540             iface->RemoveRoute(route);
       
 10541         else
       
 10542             route->iMetric = opt.iMetric;
       
 10543 
       
 10544         ScanHoldings();
       
 10545         return KErrNone;
       
 10546         }
       
 10547     return KErrNotSupported;
       
 10548     }
       
 10549 
       
 10550 
       
 10551 TInt CIp6Manager::SetIpv4LinkLocalOption(const TSoInetIpv4LinkLocalInfo &aOption)
       
 10552     {
       
 10553     CIp6Interface *iface = FindInterface(aOption.iInterface);
       
 10554     if (iface == NULL)
       
 10555         return KErrNotFound;
       
 10556         
       
 10557     return iface->SetIpv4LinkLocal(aOption.iFlag);
       
 10558     }
       
 10559     
       
 10560     
       
 10561 TInt CIp6Interface::SetIpv4LinkLocal(TUint aFlag)
       
 10562     /**
       
 10563     * Sets the IPv4 link-local flag for this interface.
       
 10564     * Possible parameter values are enumerated in EV4LLEnums.
       
 10565     *
       
 10566     * If the LL flag is set to disabled when link local addresses are used,
       
 10567     * the link-local prefix/id entries are set to deprecated state (without timeout)
       
 10568     * and they are left into the routing table.
       
 10569     */
       
 10570     {
       
 10571     // Unlike the ini parameter, the socket option has only two valid choices:
       
 10572     // unconditional disable and unconditional enable
       
 10573     if (aFlag > 1)
       
 10574         return KErrArgument;
       
 10575 
       
 10576     iIpv4Linklocal = aFlag;
       
 10577 
       
 10578     for (;;)    // FAKE LOOP, JUST FOR BREAK EXITS!
       
 10579         {
       
 10580         if (aFlag == EV4LLAlways)
       
 10581             {
       
 10582             // ConfigureLinkLocal() does not get confused even if it was called already
       
 10583             // earlier, so this should be safe operation
       
 10584             if (ConfigureLinkLocal(0) == 0)
       
 10585                 break;  // -- no change!
       
 10586             }
       
 10587         else if (aFlag == EV4LLDisabled)
       
 10588             {
       
 10589             // The code from this point on is only for deprecating IPv4 LL addresses when
       
 10590             // the user requests to disable LL when they were earlier enabled
       
 10591 
       
 10592             TIp6AddressInfo *const address = FindInternalIpv4LinkLocalAddr();
       
 10593             if (address == NULL)
       
 10594                 break;  // -- no change (no LL address present)
       
 10595 
       
 10596             // Found IPv4 Link-local address (Id). Mark it as deprecated.
       
 10597             // The corresponding prefix will also get deprecated in the Timeout()
       
 10598             // function
       
 10599             address->iPLT = 0;
       
 10600             // Further processing for deprecation takes place in timeout handler
       
 10601             }
       
 10602         else
       
 10603             break;  // -- no change
       
 10604         
       
 10605         // Address configuration has been changed, the process completes
       
 10606         // through the Timeout function, activate it.
       
 10607         TTime stamp;
       
 10608         stamp.UniversalTime();
       
 10609         Timeout(stamp);
       
 10610         break;  // ** ALWAYS EXIT THE FAKE LOOP
       
 10611         }
       
 10612     return KErrNone;
       
 10613     }
       
 10614 
       
 10615 
       
 10616 // CIp6Interface::FindIpv4LinkLocalAddr
       
 10617 // ****************************************
       
 10618 /**
       
 10619 // Find the one and only internally generated IPv4 link-local, if present.
       
 10620 //
       
 10621 // @return the TIp6AddressInfo, if such address exists; and NULL otherwise.
       
 10622 */
       
 10623 const TIp6AddressInfo* CIp6Interface::FindIpv4LinkLocalAddr() const
       
 10624     {
       
 10625     for (const TIp6AddressInfo *address = &iAddress;;)
       
 10626         {
       
 10627         if( address->IsSet() && address->iIpv4LinkLocal )
       
 10628             {
       
 10629             // Caller does not get ownership of object.
       
 10630             return (TIp6AddressInfo *)address;
       
 10631             }
       
 10632 
       
 10633         if (address->iNext == NULL)
       
 10634             break;
       
 10635         address = &address->iNext->iInfo;
       
 10636         }
       
 10637     return NULL;
       
 10638     }
       
 10639 
       
 10640 
       
 10641 //
       
 10642 // CIp6Interface::NotifyFlows
       
 10643 // **************************
       
 10644 // The interface has changed the state, notify the flows about this
       
 10645 //
       
 10646 void CIp6Interface::NotifyFlows(TInt aState, TBool aForce) const
       
 10647     {
       
 10648     // Interface state has changed. Notify all affected flows
       
 10649     // which have requested to be notified.
       
 10650     // Cannot just change the flow into ready, because the
       
 10651     // hooks may have something to add also.
       
 10652     // (Call RefreshFlows()? Ugh!!.. --msa)
       
 10653     TFlowNotifyList list;
       
 10654     for (CIp6Route *rt = iRouteList; rt; rt = rt->iNext)
       
 10655         for (CIp6Flow *f = rt->iFlowList; f; f = f->iNext)
       
 10656             {
       
 10657             // Temp. kludge -- msa
       
 10658             if (f->iPathMtu == 0 || (TInt)f->iPathMtu > iPMtu)
       
 10659                 f->iPathMtu = iPMtu;    // Minor kludge, fixes the
       
 10660                                             // problem when interface
       
 10661                                             // Mtu changes the Path Mtu
       
 10662                                             // -- msa
       
 10663 
       
 10664             // iIgnoreFlowContorol is set for flows that should
       
 10665             // not enter automaticly READY/HOLD state by a signal
       
 10666             // from the interface. A separate (external) module
       
 10667             // makes the decision for such flows...
       
 10668             //
       
 10669             if (aState < 0 || !f->iIgnoreFlowControl || aForce)
       
 10670                 f->Notify(list, aState);
       
 10671             }
       
 10672     list.Deliver(aState);
       
 10673     }
       
 10674 
       
 10675 
       
 10676 //
       
 10677 // CIp6Interface::NotifyFlowsPmtu
       
 10678 // ******************************
       
 10679 // Special method to define/change the Path MTU of the 
       
 10680 // currently attached flows.
       
 10681 //
       
 10682 // The provider is not notified... should it? -- msa
       
 10683 //
       
 10684 void CIp6Interface::NotifyFlowsPmtu(const TUint aPmtu) const
       
 10685     {
       
 10686     for (const CIp6Route *rt = iRouteList; rt; rt = rt->iNext)
       
 10687         for (CIp6Flow *f = rt->iFlowList; f; f = f->iNext)
       
 10688             if (f->iPathMtu == 0 || f->iPathMtu > aPmtu)
       
 10689                 f->iPathMtu = aPmtu;
       
 10690     }
       
 10691 
       
 10692 
       
 10693 // CIp6Interface::SetChanged
       
 10694 // *************************
       
 10695 // Set iChanged for all flows on this interface
       
 10696 //
       
 10697 TInt CIp6Interface::SetChanged(const TInt aScope) const
       
 10698     {
       
 10699     if (aScope > 0)
       
 10700         return Interfacer().SetChanged();
       
 10701     TInt count = 0;
       
 10702     for (CIp6Route *rt = iRouteList; rt; rt = rt->iNext)
       
 10703         count += rt->SetChanged(0);
       
 10704     return count;
       
 10705     }
       
 10706 
       
 10707 //
       
 10708 // CIp6Manager::SetChanged
       
 10709 // ***********************
       
 10710 // Set iChanged for all flows
       
 10711 //
       
 10712 TInt CIp6Manager::SetChanged() const
       
 10713     {
       
 10714     TInt count = 0;
       
 10715     for (CIp6Interface *iface = iInterfaceList; iface != NULL; iface = iface->iNext)
       
 10716         count += iface->SetChanged(0);
       
 10717     return count;
       
 10718     }
       
 10719 
       
 10720 //
       
 10721 // CIp6Manager::FindInterface
       
 10722 // **************************
       
 10723 /**
       
 10724 // Based on CNifIfBase pointer, locate the internal
       
 10725 // CIp6Interface description that is connected to the
       
 10726 // this interface. Returns NULL, if none found.
       
 10727 //
       
 10728 // WARNING: (conserns both FindInterface methods)
       
 10729 //      The search key is a pointer to memory block representing some
       
 10730 //      structure and the point of these lookups is to guarantee that
       
 10731 //      this value is still valid. However, there is a potential
       
 10732 //      problem if the object being searched gets released and another
       
 10733 //      object of the same type gets created using the same memory
       
 10734 //      address. In such case FindInterface may return wrong interface!
       
 10735 //      -- msa [needs to be checked whether this is a problem!]
       
 10736 */
       
 10737 CIp6Interface *CIp6Manager::FindInterface(const CNifIfBase *aInterface) const
       
 10738     {
       
 10739     if (aInterface == NULL)
       
 10740         return NULL;    // Don't search for NULL!
       
 10741     for (CIp6Interface *iface = iInterfaceList; iface != NULL; iface = iface->iNext)
       
 10742         if (iface->iNifIf == aInterface)
       
 10743             return iface;
       
 10744     return NULL;
       
 10745     }
       
 10746 //
       
 10747 // CIp6Manager::FindInterface
       
 10748 /**
       
 10749 //      This is mainly to safely convert aId parameter from MNifIfuser
       
 10750 //      upcall into valid CIp6Interface pointer. (Just makes sure that
       
 10751 //      the instance referred by aId really exists.
       
 10752 */
       
 10753 CIp6Interface *CIp6Manager::FindInterface(const TAny *aId) const
       
 10754     {
       
 10755     for (CIp6Interface *iface = iInterfaceList; iface != NULL; iface = iface->iNext)
       
 10756         if (iface == aId)
       
 10757             return iface;
       
 10758     return NULL;
       
 10759     }
       
 10760 //
       
 10761 // CIp6Manager::FindInterface
       
 10762 //     Locate interface by address
       
 10763 CIp6Interface *CIp6Manager::FindInterface(const TInetAddr &aAddr) const
       
 10764     {
       
 10765     const TIp46Addr addr(aAddr);
       
 10766     const TUint32 scope_type = addr.Scope() - 1;
       
 10767     if (scope_type > EScopeType_NET)
       
 10768         return NULL;
       
 10769     const TUint32 scope_id = aAddr.Scope();
       
 10770     for (CIp6Interface *iface = iInterfaceList; iface != NULL; iface = iface->iNext)
       
 10771         {
       
 10772         const TUint32 if_scope = iface->iScope[scope_type];
       
 10773         if ((if_scope == 0 || scope_id == 0 || if_scope == scope_id) && iface->IsMyAddress(addr))
       
 10774             return iface;
       
 10775         }
       
 10776     return NULL;
       
 10777     }
       
 10778 
       
 10779 //
       
 10780 // CIp6Manager::FindInterface
       
 10781 //     Locate interface by Interface index
       
 10782 CIp6Interface *CIp6Manager::FindInterface(const TUint32 aIndex) const
       
 10783     {
       
 10784     return FindInterface(aIndex, EScopeType_IF);
       
 10785     }
       
 10786 
       
 10787 // CIp6Manager::FindInterface
       
 10788 //     Locate Interface by a specific scope id.
       
 10789 //     Note, that there can be multiple interfaces which match
       
 10790 //     the condition. Only the first located is returned.
       
 10791 CIp6Interface *CIp6Manager::FindInterface(const TUint32 aIndex, const TScopeType aLevel) const
       
 10792     {
       
 10793     for (CIp6Interface *iface = iInterfaceList; iface != NULL; iface = iface->iNext)
       
 10794         if (iface->iScope[aLevel] == aIndex)
       
 10795             return iface;
       
 10796     return NULL;
       
 10797     }
       
 10798 
       
 10799 // CIp6Manager::FindInterface
       
 10800 //     Locate Interface mathing the specified name
       
 10801 CIp6Interface *CIp6Manager::FindInterface(const TDesC &aName) const
       
 10802     {
       
 10803     for (CIp6Interface *iface = iInterfaceList; iface; iface = iface->iNext)
       
 10804         if (aName.Compare(iface->iName) == 0)
       
 10805             return iface;
       
 10806     return NULL;
       
 10807     }
       
 10808     
       
 10809 
       
 10810 
       
 10811 // CIp6Manager::Interface
       
 10812 // **********************
       
 10813 //
       
 10814 const MInterface* CIp6Manager::Interface(const CNifIfBase *const aIf) const
       
 10815     {
       
 10816     return FindInterface(aIf);
       
 10817     }
       
 10818 
       
 10819 const MInterface* CIp6Manager::Interface(const TDesC &aName) const
       
 10820     {
       
 10821     return FindInterface(aName);
       
 10822     }
       
 10823 
       
 10824 const MInterface* CIp6Manager::Interface(const TUint32 aInterfaceIndex) const
       
 10825     {
       
 10826     return FindInterface(aInterfaceIndex);
       
 10827     }
       
 10828 
       
 10829 //
       
 10830 // CIp6Manager::StartSending
       
 10831 // *************************
       
 10832 //
       
 10833 TInt CIp6Manager::StartSending(CNifIfBase *aIface)
       
 10834     {
       
 10835     if (aIface)
       
 10836         {
       
 10837         CIp6Interface* iface = FindInterface((CNifIfBase*)aIface);
       
 10838         if (iface)
       
 10839             {
       
 10840             LOG(Log::Printf(_L("\tIF %u [%S] StartSending"), iface->iScope[0], &iface->iName));
       
 10841             const TInt transition = iface->StartSending();
       
 10842             //
       
 10843             // StartSending from an interface implies that it is
       
 10844             // in READY state (can accept Send()). However this
       
 10845             // does not directly mean that flows can be opened
       
 10846             // yet. Update may have decided that information is
       
 10847             // still missing (prefixes, return PENDING) or detected
       
 10848             // some configuration error (return < 0). Other than
       
 10849             // pending, should be notified to flows.
       
 10850             //
       
 10851             LOG(Log::Printf(_L("\tIF %u [%S] StartSending, transition=%d"), iface->iScope[0], &iface->iName, transition));
       
 10852             if (transition != KIfaceTransition_NONE)
       
 10853                 {
       
 10854                 iface->NotifyFlows(transition > 0 ? EFlow_READY : transition);
       
 10855                 // if transition is UP, try waking up the holding flows
       
 10856                 // (try to re-attach pending flows, in case this new interface fits
       
 10857                 // some of them...)
       
 10858                 if (transition == KIfaceTransition_UP)
       
 10859                     ScanHoldings();
       
 10860                 }
       
 10861             return transition;
       
 10862             }
       
 10863         else
       
 10864             return KIfaceTransition_DOWN;
       
 10865         }
       
 10866     else
       
 10867         return KIfaceTransition_NONE;
       
 10868     }
       
 10869 //
       
 10870 // CIp6Manager::Error
       
 10871 // ******************
       
 10872 //
       
 10873 // Comment/msa: It is somewhat unclear what it means when an interface
       
 10874 // calls Error() of the network layer. What is the expected effect?
       
 10875 //
       
 10876 // a) just report it to flows, but leave interface into OK state?
       
 10877 // b) report to flows, put interface into error state until
       
 10878 //    either StartSending() clears it, or interface goes down?
       
 10879 //
       
 10880 // The current implementaion does (b).
       
 10881 //
       
 10882 TInt CIp6Manager::Error(TInt aError, CNifIfBase *aIface)
       
 10883     {
       
 10884     if (aIface)
       
 10885         {
       
 10886         CIp6Interface* iface = FindInterface((CNifIfBase*)aIface);
       
 10887         if (iface)
       
 10888             {
       
 10889             LOG(Log::Printf(_L("CIp6Manager::Error(%d, %S)"), aError, &iface->iName));
       
 10890 
       
 10891             if (iface->iState >= EFlow_READY)
       
 10892                 iface->iState = aError;
       
 10893             //
       
 10894             // Notify flows that want interface errors...
       
 10895             //
       
 10896             if (aError < 0)
       
 10897                 {
       
 10898                 iface->NotifyFlows(aError);
       
 10899                 //
       
 10900                 // For the remaining flows, interface going down is not a fatal
       
 10901                 // error. Move all attached flow to the holding route (pending state).
       
 10902                 //
       
 10903                 // Note: if there is no holding route, flows will be terminated
       
 10904                 // by the Reset().
       
 10905                 for (CIp6Route *rt = iface->iRouteList; rt != NULL; rt = rt->iNext)
       
 10906                     MoveToHolding(*rt);
       
 10907                 iface->Reset(1);    // Reset to initial state, but keep binding to NIF
       
 10908                 }
       
 10909             }
       
 10910         //
       
 10911         // This is somewhat kludgy. Allow Error to used by the interface to set the
       
 10912         // interface state into non-error state (like pending). If such call happens,
       
 10913         // return with NONE transition to prevent unnecessary further processing.
       
 10914         return aError < 0 ? aError : KIfaceTransition_NONE;
       
 10915         }
       
 10916     else
       
 10917         return KIfaceTransition_NONE;
       
 10918     }
       
 10919 
       
 10920 
       
 10921 //
       
 10922 // CIp6Manager::IcmpHandler
       
 10923 // ************************
       
 10924 /**
       
 10925 // Gets a peek at all received non-error ICMP's
       
 10926 //
       
 10927 // @return
       
 10928 // @li < 0, if packet has been released (packet will not
       
 10929 //          go to the upper layer after this),
       
 10930 // @li  = 0,    the usual return, packet looked and it can be
       
 10931 //          passed to the upper layers
       
 10932 // @li  > 0,    *NOT USED NOW*, Treat as = 0 as default
       
 10933 */
       
 10934 TInt CIp6Manager::IcmpHandler(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo)
       
 10935     {
       
 10936     if (aInfo.iProtocol != STATIC_CAST(TInt,KProtocolInet6Icmp))
       
 10937         return 0;       // For now, only ICMP6 is interesting!
       
 10938     //
       
 10939     // For validity checking, the hoplimit/TTL is required.. get it..
       
 10940     //
       
 10941     const TIpHeader *const ip = ((RMBufPacketPeek &)aPacket).GetIpHeader();
       
 10942     if (!ip)
       
 10943         return 0;       // should probably drop the packet
       
 10944     if (255 != ((aInfo.iVersion == 4) ? ip->ip4.Ttl() : ip->ip6.HopLimit()))
       
 10945         return 0;       // All ND ICMP's must have hoplimit == 255!
       
 10946 
       
 10947     TInet6Packet<TIcmpNdHeader> nd(aPacket, aInfo.iOffset);
       
 10948 
       
 10949     if (nd.iHdr == NULL ||
       
 10950         nd.iHdr->iIcmp.Code() != 0)
       
 10951         return 0;       // Not for me!
       
 10952 
       
 10953     CIp6Interface *const srcif = FindInterface(aInfo.iInterfaceIndex);
       
 10954     if (!srcif)
       
 10955         return 0;
       
 10956     return srcif->IcmpHandler(aPacket, aInfo, nd);
       
 10957     }
       
 10958 
       
 10959 
       
 10960 //
       
 10961 // CIp6Interface::IcmpHandler
       
 10962 // **************************
       
 10963 /**
       
 10964 // The CIp6Manager::IcmpHandler determined that the basic ICMP is
       
 10965 // valid (for ND), and belongs to the current interface, where
       
 10966 // the actual ICMP processing occurs.
       
 10967 //
       
 10968 // @return
       
 10969 // @li  < 0,    if packet has been released (packet will not
       
 10970 //          go to the upper layer after this),
       
 10971 // @li  = 0,    the usual return, packet looked and it can be
       
 10972 //          passed to the upper layers
       
 10973 // @li  > 0,    *NOT USED NOW*, Treat as = 0 as default
       
 10974 */
       
 10975 TInt CIp6Interface::IcmpHandler(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo, TInet6Packet<TIcmpNdHeader>  &aNd)
       
 10976     {
       
 10977 #ifdef SYMBIAN_TCPIPDHCP_UPDATE      
       
 10978     #ifdef _DEBUG
       
 10979         LOG(Log::Printf(_L("<>\tCIp6Interface::IcmpHandler()")));
       
 10980     #endif
       
 10981 #endif // SYMBIAN_TCPIPDHCP_UPDATE          
       
 10982     TInt notify = 0;
       
 10983 #ifndef SYMBIAN_TCPIPDHCP_UPDATE
       
 10984     TInt dns_flag = 0;
       
 10985 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
 10986     TInt count, start;
       
 10987 
       
 10988     const TInt icmp_type = aNd.iHdr->iIcmp.Type();
       
 10989     TLinkAddr source_link, target_link;
       
 10990 
       
 10991     const TIp6Addr &icmp_src_addr = TInetAddr::Cast(aInfo.iSrcAddr).Ip6Address();
       
 10992     const TIp6Addr &icmp_dst_addr = TInetAddr::Cast(aInfo.iDstAddr).Ip6Address();
       
 10993 
       
 10994 #ifdef _LOG
       
 10995     // src & dst for logging purposes
       
 10996     TBuf<70> tmpsrc, tmpdst;
       
 10997     TInetAddr::Cast(aInfo.iSrcAddr).OutputWithScope(tmpsrc);
       
 10998     TInetAddr::Cast(aInfo.iDstAddr).OutputWithScope(tmpdst);
       
 10999 #endif
       
 11000 
       
 11001 
       
 11002     // Setup and Check Validity (part of it)
       
 11003     // *************************************
       
 11004     //
       
 11005     // The ICMP source address can only be either a valid unicast address
       
 11006     // or unspecified address in some cases for RS and NS.
       
 11007     //
       
 11008     const TInt icmp_src_unspecified = icmp_src_addr.IsUnspecified();
       
 11009     if (TIp46Addr::Cast(icmp_src_addr).IsMulticast())
       
 11010         goto drop_packet;   // Was not unicast or unspecified
       
 11011 
       
 11012     switch (icmp_type)
       
 11013         {
       
 11014         case KInet6ICMP_RouterSol:
       
 11015             LOG(Log::Printf(_L("\tIF %u [%S] Received RS src=[%S] dst=[%S]"), iScope[0], &iName, &tmpsrc, &tmpdst));
       
 11016             start = aNd.iHdr->iRS.HeaderLength();
       
 11017             break;
       
 11018         case KInet6ICMP_RouterAdv:
       
 11019             //
       
 11020             // A Router Advertisement ICMP detected
       
 11021             //
       
 11022             LOG(Log::Printf(_L("\tIF %u [%S] Received RA src=[%S] dst=[%S]"), iScope[0], &iName, &tmpsrc, &tmpdst));
       
 11023             if (!icmp_src_addr.IsLinkLocal())   // .. src must be a link local address.
       
 11024                 goto drop_packet;
       
 11025             start = aNd.iHdr->iRA.HeaderLength();
       
 11026             break;
       
 11027         case KInet6ICMP_NeighborSol:
       
 11028             LOG(Log::Printf(_L("\tIF %u [%S] Received NS src=[%S] dst=[%S]"), iScope[0], &iName, &tmpsrc, &tmpdst));
       
 11029             start = aNd.iHdr->iNS.HeaderLength();
       
 11030             // RFC-2461 says to require !Multicast.. but, that would let Unspecified through!
       
 11031             // Is it an error in RFC or not? (Need to check message length here, becuase of
       
 11032             // accessing of the target field!)
       
 11033             if (start > aNd.iLength || !aNd.iHdr->iNS.Target().IsUnicast())
       
 11034                 goto drop_packet;
       
 11035             // The NS destination address is either the target address or..
       
 11036             if (!icmp_dst_addr.IsEqual(aNd.iHdr->iNS.Target()))
       
 11037                 {
       
 11038                 // ..it must be the solicited node multicast corresponding
       
 11039                 // the target address (RFC-2461, 4.3)
       
 11040                 TSolicitedNodeAddr solicited(aNd.iHdr->iNS.Target());
       
 11041                 if (!icmp_dst_addr.IsEqual(solicited))
       
 11042                     goto drop_packet;
       
 11043                 }
       
 11044             else if (icmp_src_unspecified)
       
 11045                 // ..apparently, src=:: && target==dst is invalid combination
       
 11046                 // (TAHI), and packet must be dropped...
       
 11047                 goto drop_packet;
       
 11048             break;
       
 11049         case KInet6ICMP_NeighborAdv:
       
 11050             LOG(Log::Printf(_L("\tIF %u [%S] Received NA src=[%S] dst=[%S]"), iScope[0], &iName, &tmpsrc, &tmpdst));
       
 11051             start = aNd.iHdr->iNA.HeaderLength();
       
 11052             // RFC-2461 says to require target != Multicast.. but, that would let Unspecified through!
       
 11053             // Is it an error in RFC or not? (Need to check message length here, becuase of
       
 11054             // accessing of the target field!)
       
 11055             if (icmp_src_unspecified || start > aNd.iLength || !aNd.iHdr->iNA.Target().IsUnicast())
       
 11056                 goto drop_packet;
       
 11057             // Note: Solicited bit/Target Link-layer option vs. multicast destination
       
 11058             // check is performed after the options pass (see there.) [Can do this,
       
 11059             // because *currently* none of the NA option processing "commits" any
       
 11060             // changes to the system state.. however, watch it -- msa]
       
 11061             break;
       
 11062         case KInet6ICMP_Redirect:
       
 11063             LOG(Log::Printf(_L("\tIF %u [%S] Received Redirect src=[%S] dst=[%S]"), iScope[0], &iName, &tmpsrc, &tmpdst));
       
 11064             if (!icmp_src_addr.IsLinkLocal())   // .. src must be a link local address.
       
 11065                 goto drop_packet;
       
 11066             start = aNd.iHdr->iRD.HeaderLength();
       
 11067             if (start > aNd.iLength || !aNd.iHdr->iRD.Destination().IsUnicast())
       
 11068                 goto drop_packet;
       
 11069             break;
       
 11070         default:
       
 11071             return 0;           // Not for me
       
 11072         }
       
 11073     //
       
 11074     // Process Options
       
 11075     // ***************
       
 11076     // (to be 100% right in everything, one should probably make
       
 11077     // this section a separate method with two operating modes, and
       
 11078     // which is called twice in processing the ND ICMP: (1) to check
       
 11079     // validity of everything, and if all is OK, (2) execute the
       
 11080     // options. -- msa)
       
 11081     //
       
 11082     // Note: *Currently* only RA's may run into this problem, because
       
 11083     // RA is the only ND ICMP, in which the options are actually
       
 11084     // "committed" directly in the options processing (Prefix, Mtu).
       
 11085     //
       
 11086     start += aInfo.iOffset;
       
 11087     count = aInfo.iLength - start;
       
 11088     if (count < 0)
       
 11089         goto drop_packet;       // Message is too short to be valid ND.
       
 11090     while (count > 0)
       
 11091         {
       
 11092         TIcmpNdOption option;
       
 11093         TPtr8 opt((TUint8 *)&option, sizeof(option), sizeof(option));
       
 11094 
       
 11095         RMBuf *p;
       
 11096         TInt offset, len;
       
 11097         TUint8 *ptr, type;
       
 11098 
       
 11099         if (!aPacket.Goto(start, p, offset, len))
       
 11100             return 0;       // Drop instead?
       
 11101         ptr = p->Buffer() + offset;
       
 11102         type = *ptr++;
       
 11103         --len;
       
 11104         while (len == 0)    // Should loop only once, but 'while' just in
       
 11105                             // case someone wants RMBuf with zero length...
       
 11106             {
       
 11107             p = p->Next();
       
 11108             if (p == NULL)
       
 11109                 return 0;
       
 11110             len = p->Length();
       
 11111             ptr = p->Ptr();
       
 11112             }
       
 11113         len = *ptr;
       
 11114         //
       
 11115         // All included options must have length > 0. However, by coding
       
 11116         // it this way, there is a problem that all preceding valid options
       
 11117         // have already been executed and system state may have been changed
       
 11118         // for those. To fully comply, one should do two passes over the
       
 11119         // options, first to check the validity and then execute. -- msa 
       
 11120         if (len < 1)
       
 11121             goto drop_packet;   // Option length < 1, drop packet!
       
 11122         len <<= 3;
       
 11123         // We don't want panic from perfectly legal but unknown to us
       
 11124         // options that are longer than any of the "known" ones. Thus,
       
 11125         // constrain SetLength()...
       
 11126         opt.SetLength(len > opt.MaxLength() ? opt.MaxLength() : len);
       
 11127         aPacket.CopyOut(opt, start);
       
 11128         switch (type)
       
 11129             {
       
 11130             // source and target link options are only accepted, if the
       
 11131             // link layer supports addresses, and ignored otherwise.
       
 11132 
       
 11133             case KInet6OptionICMP_SourceLink:   // Source link-layer address
       
 11134                 if (icmp_src_unspecified)
       
 11135                     goto drop_packet;           // Illegal, if unspecified source!
       
 11136                 if (iHwAddr.Family() != KAFUnspec)
       
 11137                     {
       
 11138                     source_link.SetAddress(option.iLink.Address());
       
 11139                     source_link.SetFamily(iHwAddr.Family());
       
 11140                     }
       
 11141                 break;
       
 11142             case KInet6OptionICMP_TargetLink:   // Target link-layer address
       
 11143                 if (iHwAddr.Family() != KAFUnspec)
       
 11144                     {
       
 11145                     target_link.SetAddress(option.iLink.Address());
       
 11146                     target_link.SetFamily(iHwAddr.Family());
       
 11147                     }
       
 11148                 break;
       
 11149             case KInet6OptionICMP_Mtu:          // MTU
       
 11150                 if (icmp_type == KInet6ICMP_RouterAdv)
       
 11151                     SetMtu(option.iMtu.Mtu(), KInet6MinMtu);
       
 11152                 break;
       
 11153             case KInet6OptionICMP_Prefix:       // Prefix Information
       
 11154                 if (icmp_type == KInet6ICMP_RouterAdv && !option.iPrefix.Prefix().IsLinkLocal())
       
 11155                     {
       
 11156                     const TInt length = option.iPrefix.PrefixLength();
       
 11157                     const TLifetime lifetime = option.iPrefix.ValidLifetime();
       
 11158                     const TLifetime preferred = option.iPrefix.PreferredLifetime();
       
 11159 
       
 11160                     if (length > 128)
       
 11161                         goto drop_packet;   // Garbage!
       
 11162                     if (preferred > lifetime)
       
 11163                         break;              // Ignore Option with illogical lifetimes
       
 11164                     if (option.iPrefix.AFlag()) // Can use this for address generation?
       
 11165                         // ...should set the aForce flag, if RA was protected by IPSEC... -- msa
       
 11166                         {
       
 11167 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
 11168                         #ifdef _DEBUG
       
 11169                             LOG(Log::Printf(_L("<>\tCIp6Interface::IcmpHandler() option.iPrefix.AFlag()")));
       
 11170                         #endif
       
 11171                         iGlobalflag = ETrue; 
       
 11172 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
 11173                         SetPrefix(option.iPrefix.Prefix(), length, !NeedsND(), lifetime, preferred);
       
 11174                         }
       
 11175                     // Note: now multicasts and unspecified addresses are accepted.
       
 11176                     // Is this a "feature" or should it be prevented? -- msa
       
 11177                     if (option.iPrefix.LFlag())
       
 11178                         (void)GetRoute(option.iPrefix.Prefix(), length, KRouteAdd_ONLINK, NULL, &lifetime);
       
 11179                     notify++;   // .. only for new prefixes.
       
 11180                     }
       
 11181                 break;
       
 11182 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
 11183 //RFC 5006 Changes
       
 11184             case KInet6OptionICMP_RDNSS:
       
 11185                 // Process RDNSS only if M Flag is set
       
 11186                 if (aNd.iHdr->iRA.M()) 
       
 11187                     {
       
 11188                     if(iRdnssList == NULL)
       
 11189                         {
       
 11190                         iRdnssList = CManageRdnssServerList::NewL();                                
       
 11191                         }       
       
 11192                     if( (aNd.iHdr->iRA.RouterLifetime())!= 0)
       
 11193                         {   
       
 11194                         LOG(Log::Printf(_L("\tIF %u [%S] RECEIVED RDNSS OPTION"), iScope[0], &iName));
       
 11195                         TInet6OptionICMP_DnsInformationV1 rdnssOption = option.iDnsInformation;
       
 11196                                         
       
 11197                         TUint8 numRdnssAddr;
       
 11198                         if(iRdnssList->RdnssParseOptionHdr(rdnssOption,numRdnssAddr))
       
 11199                             {                               
       
 11200                             //Update the received RDNSS entry into RDNSServerList
       
 11201                             iRdnssList->RdnssProcessOptionData(rdnssOption, numRdnssAddr);
       
 11202                             iRdnssList->RdnssNameServerUpdate(iNameSer1,(TUint8)0);
       
 11203                             iRdnssList->RdnssNameServerUpdate(iNameSer2,(TUint8)1);
       
 11204                             }
       
 11205                         else
       
 11206                             {
       
 11207                             delete iRdnssList;
       
 11208                             iRdnssList = NULL;
       
 11209                             goto drop_packet;
       
 11210                             }
       
 11211                         }
       
 11212                     else
       
 11213                         // Router Lifetime is 0, Delete all RDNSS entries
       
 11214                         {
       
 11215                         iRdnssList->RdnssServerListDelete();    
       
 11216                         // Reset Respository iNameServer1 and iNameServer2 to KAFUnspec 
       
 11217                         iRdnssList->RdnssNameServerReset(iNameSer1,iRdnssList->GetRdnssFlag());
       
 11218                         iRdnssList->RdnssNameServerReset(iNameSer2,iRdnssList->GetRdnssFlag());                 
       
 11219                         }
       
 11220                         
       
 11221                     }
       
 11222                 break;
       
 11223 #endif // SYMBIAN_TCPIPDHCP_UPDATE
       
 11224             default:
       
 11225                 // Handle options, for which is is no fixed assigned type by IANA, and which are
       
 11226                 // configured via TCPIP.INI. Option is enabled, if a non-zero type code is configured.
       
 11227                 // Because the 0 value has own case in switch, there is no need to test against
       
 11228                 // ZERO here (unconfigured option type is ZERO and never matches).
       
 11229                 if (icmp_type == KInet6ICMP_RouterAdv)
       
 11230                     {
       
 11231                     if (type == Interfacer().iRA_OptRoute)
       
 11232                         {
       
 11233                         // Route Information Option 
       
 11234                         // Experimental: draft-draves-ipngwg-router-selection-01.txt
       
 11235                         // Default Router Preferences and More-Specific Routes
       
 11236                         //
       
 11237                         const TInt preference = option.iRouteInformation.Prf(); // range guaranteed to be [0..3]!
       
 11238                         if (preference == ERoutePreference_INVALID)
       
 11239                             break;  // invalid preference value
       
 11240                         if (option.iRouteInformation.PrefixLength() > 128)
       
 11241                             goto drop_packet;   // Garbage !
       
 11242                         const TLifetime lifetime = option.iRouteInformation.RouteLifetime();
       
 11243                         // Because the option is copied into a temporary space, Prefix() method is
       
 11244                         // "safe" to use... (see comment on it's definition!). (However, might
       
 11245                         // consider opt.FillZ before CopyOut to remove possible distracting, but
       
 11246                         // harmless garbage.
       
 11247                         CIp6Route *const route = GetRoute(
       
 11248                             option.iRouteInformation.Prefix(),
       
 11249                             option.iRouteInformation.PrefixLength(),
       
 11250                             KRouteAdd_GATEWAY,
       
 11251                             &aInfo.iSrcAddr,        // The gateway address
       
 11252                             &lifetime);
       
 11253                         if (route)
       
 11254                             route->iMetric = KPreferenceMetric[preference];
       
 11255                         }
       
 11256 #ifndef SYMBIAN_TCPIPDHCP_UPDATE
       
 11257                     else if (type == Interfacer().iRA_OptDns)
       
 11258                              {
       
 11259                              // Experimental: draft-jeong-dnsop-ipv6-discovery-03.txt
       
 11260                              // IPv6 DNS Configuration based on Router Advertisement
       
 11261                              //
       
 11262                              // *WARNING* Just a "proof of concept", not complete
       
 11263                              // implementation (more like a "placeholder code", indicates
       
 11264                              // the point where real implementation should go...)
       
 11265                              // - preference is ignored
       
 11266                              // - other than "delete", lifetime is ignored
       
 11267                              // - only two first addresses processed
       
 11268                              // - does not do much sanity check (delete and insert same address).
       
 11269                              const TIp6Addr &addr = option.iDnsInformation.Address();
       
 11270                              const TLifetime lifetime = option.iDnsInformation.Lifetime();
       
 11271                              if (lifetime == 0)
       
 11272                                  {
       
 11273                                  // Should remove the matching DNS server address
       
 11274                                  // (if present)
       
 11275                                  if (iNameSer1.Ip6Address().IsEqual(addr))
       
 11276                                      {
       
 11277                                      iNameSer1.Init(KAFUnspec);
       
 11278                                      dns_flag |= 4;  // mark "dns changed"
       
 11279                                      }
       
 11280                                  if (iNameSer2.Ip6Address().IsEqual(addr))
       
 11281                                      {
       
 11282                                      iNameSer2.Init(KAFUnspec);
       
 11283                                      dns_flag |= 4;  // mark "dns changed"
       
 11284                                      }
       
 11285                                  }
       
 11286                              else if (!addr.IsUnspecified())
       
 11287                                  {
       
 11288                                  // Add DNS server address
       
 11289                                  // (ignore prefs, take the first two)
       
 11290                                  if ((dns_flag&1) == 0)
       
 11291                                      {
       
 11292                                      iNameSer1.SetAddress(addr);
       
 11293                                      dns_flag |= 1;
       
 11294                                      }
       
 11295                                  else if ((dns_flag&2) == 0)
       
 11296                                      {
       
 11297                                      iNameSer2.SetAddress(addr);
       
 11298                                      dns_flag |= 2;
       
 11299                                      }
       
 11300                                  }
       
 11301                              }
       
 11302 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
 11303                     }
       
 11304                 break;
       
 11305             case 0: // To avoid getting into default branch with type==0!
       
 11306                 break;
       
 11307             }
       
 11308         //
       
 11309         // Advance to the next option
       
 11310         //
       
 11311         count -= len;
       
 11312         start += len;
       
 11313         }
       
 11314 
       
 11315     //
       
 11316     // Execute the actual ND ICMP
       
 11317     // **************************
       
 11318     //
       
 11319     TIp6AddressInfo *my_id;
       
 11320 
       
 11321     switch (icmp_type)
       
 11322         {
       
 11323         case KInet6ICMP_RouterAdv:
       
 11324             //
       
 11325             // The router is advertising as a default route
       
 11326             // Add a default route entry (will also handle changes
       
 11327             // in the lifetime and even destruction, if lifetime == 0.
       
 11328             //
       
 11329             // *NOTE* Even if the RouterLifeTime is 0, ISROUTER is set, because
       
 11330             // this is a valid router, it's just not a default router.
       
 11331             //
       
 11332             (void)GetRoute(icmp_src_addr, 128, KRouteAdd_OVERRIDE|KRouteAdd_ISROUTER, &source_link);
       
 11333                 {
       
 11334                 const TInt preference = aNd.iHdr->iRA.Prf(); // range guaranteed to be [0..3]!
       
 11335                 // If prf is invalid, don't install default route!
       
 11336                 const TLifetime lifetime = (preference == ERoutePreference_INVALID) ? 0 : aNd.iHdr->iRA.RouterLifetime();
       
 11337                 // Disable Router Discovery process (sending RS's), if
       
 11338                 // at least one RS has been sent, see RFC 2461 6.3.7),
       
 11339                 // And if this RA had non-zero lifetime.
       
 11340                 if (lifetime && iRetryRS > 0)
       
 11341                     iRetryRS = KMaxTUint8;  // ...should be large enough!
       
 11342                 CIp6Route *const route = GetRoute(KInet6AddrNone, 0, KRouteAdd_GATEWAY, &aInfo.iSrcAddr, &lifetime);
       
 11343                 if (route)
       
 11344                     route->iMetric = KPreferenceMetric[preference];
       
 11345                 }
       
 11346             notify++;
       
 11347             if (aNd.iHdr->iRA.ReachableTime() && aNd.iHdr->iRA.ReachableTime() != iND.iReachableTime)
       
 11348                 {
       
 11349                 iND.iReachableTime = aNd.iHdr->iRA.ReachableTime();
       
 11350                 SetReachableTime();
       
 11351                 }
       
 11352             if (aNd.iHdr->iRA.RetransTimer() && aNd.iHdr->iRA.RetransTimer() != iND.iRetransTimer)
       
 11353                 {
       
 11354                 iND.iRetransTimer = aNd.iHdr->iRA.RetransTimer();
       
 11355                 SetRetransTimer();
       
 11356                 }
       
 11357             if (aNd.iHdr->iRA.CurHopLimit())
       
 11358                 iHopLimit = aNd.iHdr->iRA.CurHopLimit();
       
 11359             break;
       
 11360         case KInet6ICMP_NeighborSol:
       
 11361             {
       
 11362 #ifdef SYMBIAN_TCPIPDHCP_UPDATE              
       
 11363             #ifdef _DEBUG
       
 11364                 LOG(Log::Printf(_L("<>\tCIp6Interface::IcmpHandler() KInet6ICMP_NeighborSol recieved NS")));
       
 11365             #endif
       
 11366 #endif //SYMBIAN_TCPIPDHCP_UPDATE                  
       
 11367             // include proxy into "my address" class
       
 11368             TIp6Addr &target = aNd.iHdr->iNS.Target();
       
 11369             my_id = IsMyAddress(target, 1);
       
 11370             if (my_id == NULL)
       
 11371                 {
       
 11372                 // Target is not my assigned address, ...
       
 11373                 if (!icmp_src_unspecified)
       
 11374                     break;
       
 11375                 // ..., but the NS was a DAD probe. Check if
       
 11376                 // the plain ID part matches with any of my id's (including tentative ones)...
       
 11377                 //
       
 11378                 // * REQUIRE ID IS USED ONLY BY ONE HOST *
       
 11379                 //
       
 11380                 my_id = IsMyId(target);
       
 11381                 if (my_id == NULL)
       
 11382                     break;      // Target has no relation with me, ignore NS.
       
 11383                 if (my_id->IsTentative())
       
 11384                     {
       
 11385                     //
       
 11386                     // Someone is doing Duplicate Address Detection on my tentative address!
       
 11387                     // Decide this a duplicate address collision..
       
 11388                     //
       
 11389                     RemId(my_id);       // Kill this ID
       
 11390                     notify++;
       
 11391                     break;
       
 11392                     }
       
 11393                 //
       
 11394                 // Someone is doing Duplicate Address Detection on a address with a prefix
       
 11395                 // which is not used by me currently (because IsMyAddress() failed, but the
       
 11396                 // ID part matches one of my assigned id's. [If I ever acquire the same prefix,
       
 11397                 // there will be a collisions and confusion...].
       
 11398                 //
       
 11399                 // Could try to kill it by sending DAD probe, but that would result immediate
       
 11400                 // packet storm, if two hosts on the net had this strategy... -- msa
       
 11401                 // Instead, fall through to the standard NA code (and "incorrectly" just advertise the
       
 11402                 // address...)
       
 11403                 if (Interfacer().iNoDefendId)
       
 11404                     break; // "Defending ID" has been disabled, ignore DAD NS
       
 11405                 }
       
 11406             //
       
 11407             // Normal/DAD NS for my assigned address
       
 11408             //
       
 11409             CIp6Route *route = NULL;
       
 11410             const TIp6Addr *dst = &KInet6AddrAllNodes;
       
 11411             if (!icmp_src_unspecified)
       
 11412                 {
       
 11413                 dst = &icmp_src_addr;
       
 11414                 // We need the route entry, whether link layer is known or not
       
 11415                 route = GetRoute(*dst, 128, KRouteAdd_OVERRIDE, &source_link);
       
 11416                 if (!route)
       
 11417                     break;      // No route, and it couldn't be created for some reason!
       
 11418                 // Things get awkward if there is no cached link layer address
       
 11419                 // to be used in the reply.
       
 11420                 if (route->iState == CIp6Route::EIncomplete)
       
 11421                     route->StartND(my_id->iId);// Use my link local as ND source!
       
 11422                 }
       
 11423 #ifdef SYMBIAN_TCPIPDHCP_UPDATE              
       
 11424             //If it is DADNS,the solicitation's Source Address is unspecified then the destination address for the NA should be 
       
 11425             //the all-nodes multicast address(Refer RFC 4861 sec 4.4)
       
 11426             else if(icmp_src_unspecified)
       
 11427                 {
       
 11428                 #ifdef _DEBUG
       
 11429                     LOG(Log::Printf(_L("<>\tCIp6Interface::IcmpHandler() KInet6ICMP_NeighborSol recieved NS (icmp_src_unspecified)")));
       
 11430                 #endif
       
 11431                 //Get the target route entry
       
 11432                 CIp6Route *route1 = GetRoute(aNd.iHdr->iNS.Target(), 64, KRouteAdd_MYPREFIX | KRouteAdd_UPDATEONLY);
       
 11433                 if (route1==NULL)
       
 11434                     {
       
 11435                     //if the target route is expired/no route dont send NA
       
 11436                     #ifdef _DEBUG
       
 11437                         LOG(Log::Printf(_L("<>\tCIp6Interface::IcmpHandler() KInet6ICMP_NeighborSol recieved NS route1==NULL")));
       
 11438                     #endif
       
 11439                     break;      // No route, and it couldn't be created for some reason!
       
 11440                     }
       
 11441                 // Things get awkward if there is no cached address
       
 11442                 // to be used in the reply.
       
 11443                 if (route1->iState == CIp6Route::EIncomplete)
       
 11444                     route1->StartND(my_id->iId);// Use my target address as ND source!
       
 11445                 }
       
 11446 #endif // SYMBIAN_TCPIPDHCP_UPDATE  
       
 11447             const TInt message_type = KInet6ICMP_NeighborAdv | (my_id->IsProxy() ? KSendNeighbors_NO_OVERRIDE : 0);
       
 11448 #ifdef _LOG
       
 11449             TInetAddr tmp(route ? route->iPrefix : KInet6AddrNone, 0);
       
 11450             tmp.OutputWithScope(tmpsrc);
       
 11451             tmp.SetAddress(aNd.iHdr->iNS.Target());
       
 11452             tmp.OutputWithScope(tmpdst);
       
 11453             Log::Printf(_L("\tIF %u [%S] Sending NA(%d) dst=[%S] target=[%S]"), iScope[0], &iName, message_type, &tmpsrc, &tmpdst);
       
 11454 #endif
       
 11455             SendNeighbors(message_type, route, target);
       
 11456             }
       
 11457             break;
       
 11458         case KInet6ICMP_NeighborAdv:
       
 11459             {
       
 11460             LOG(Log::Printf(_L("<>\tCIp6Interface::IcmpHandler() KInet6ICMP_NeighborAdv recieved NA")));
       
 11461             const TInt flags = KRouteAdd_NEIGHBOR | KRouteAdd_UPDATEONLY |
       
 11462                 (aNd.iHdr->iNA.O() ? KRouteAdd_OVERRIDE : 0) |
       
 11463                 (aNd.iHdr->iNA.S() ? KRouteAdd_SOLICITED : 0) |
       
 11464                 (aNd.iHdr->iNA.R() ? KRouteAdd_ISROUTER : KRouteAdd_ISHOST);
       
 11465             // Additional "validity checks" for NA...
       
 11466             const TInt dst_is_mc = TIp46Addr::Cast(icmp_dst_addr).IsMulticast();
       
 11467             if (flags & KRouteAdd_SOLICITED)
       
 11468                 {
       
 11469                 // If destination was multicast, solicited bit cannot be set.
       
 11470                 if (dst_is_mc)
       
 11471                     goto drop_packet;
       
 11472                 }
       
 11473             TIp6Addr &target = aNd.iHdr->iNS.Target();
       
 11474             my_id = IsMyId(aNd.iHdr->iNA.Target());
       
 11475             if (my_id)
       
 11476                 {
       
 11477                 // Someone is advertising with id part matching my id???
       
 11478                 //
       
 11479                 // * REQUIRE ID IS USED ONLY BY ONE HOST *
       
 11480                 //
       
 11481                 if (my_id->IsTentative())
       
 11482                     {
       
 11483                                     
       
 11484                     // If doing Duplicate Address Detection, assume duplicate, if NA
       
 11485                     // for my tentative address is received! (RFC-2462, 5.4.4)
       
 11486                     RemId(my_id);       // Kill this ID
       
 11487                     notify++;
       
 11488                     
       
 11489 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
 11490                     //A tentative address that is determined to be a duplicate as described
       
 11491                     //above MUST NOT be assigned to an interface, and the node SHOULD log a
       
 11492                     //system management error (RFC-4862,5.4.5)
       
 11493                     iState = EFlow_NOTCONFIGURE;
       
 11494                     NotifyInterfaceEvent(EventTypeModify);
       
 11495                     LOG(Log::Printf(_L("\t Interface is not configured as DAD detects Duplicate Adress")));
       
 11496 #endif //SYMBIAN_TCPIPDHCP_UPDATE
       
 11497                     break;
       
 11498                     }
       
 11499                 //
       
 11500                 // Here is a problem: Someone is using address that has the same id part
       
 11501                 // as I have...
       
 11502                 if (IsMyAddress(target, 1))
       
 11503                     {
       
 11504                     // ..it's even my current address. Just ignore it (but, there is
       
 11505                     // another host on link using my address--this is not a good
       
 11506                     // situation!)
       
 11507                     break;
       
 11508                     }
       
 11509                 // The address has my id, but with a prefix which not configured (YET!)
       
 11510                 // for me. Accept advertisement. This works fine as long as the prefix
       
 11511                 // does not get autoconfigured for me (e.g. as long as no router
       
 11512                 // advertises it with A=1 in prefixes).
       
 11513                 }
       
 11514             if (dst_is_mc && iHwAddr.Family() != target_link.Family())
       
 11515                 // Multicast NA *MUST* have target link, if the link
       
 11516                 // is using addresses. (however, allow them to affect
       
 11517                 // DAD process and test this after that)
       
 11518                 goto drop_packet;
       
 11519             // Must not create entry, if it does not already exist
       
 11520             (void)GetRoute(target, 128, flags, &target_link);
       
 11521             }
       
 11522             break;
       
 11523         case KInet6ICMP_Redirect:
       
 11524             {
       
 11525             // More validity checks: accept redirects only if they actually come from a router that
       
 11526             // would be getting the packets sent to the specified Destination address.
       
 11527 #ifdef _LOG
       
 11528             // reuse tmpsrc for target
       
 11529             // reuse tmpdst for destination
       
 11530             TInetAddr tmp;
       
 11531             tmp.SetAddress(aNd.iHdr->iRD.Destination());
       
 11532             tmp.OutputWithScope(tmpdst);
       
 11533             tmp.SetAddress(aNd.iHdr->iRD.Target());
       
 11534             tmp.OutputWithScope(tmpsrc);
       
 11535 #endif
       
 11536             // Need to beef up the route with scope?
       
 11537             const TUint dstType = (TUint)(aNd.iHdr->iRD.Destination().Scope()-1);
       
 11538             const CIp6Route *const route =
       
 11539                 dstType > EScopeType_NET ? NULL : Interfacer().FindRoute(aNd.iHdr->iRD.Destination(), iScope[dstType], dstType);
       
 11540 
       
 11541             if (route != NULL &&
       
 11542                 &route->iInterface == this &&
       
 11543                 route->IsGateway() &&
       
 11544                 icmp_src_addr.IsEqual(route->iAddress.Ip6Address()))
       
 11545                 {
       
 11546                 LOG(Log::Printf(_L("\tIF %u [%S] Redirect [%S] to [%S] accepted"), iScope[0], &iName, &tmpdst, &tmpsrc));
       
 11547                 TInt flags = KRouteAdd_OVERRIDE;
       
 11548                 TIp6Addr &target = aNd.iHdr->iRD.Target();
       
 11549                 if (!aNd.iHdr->iRD.Destination().IsEqual(target))
       
 11550                     {
       
 11551                     if (aNd.iHdr->iRD.Target().IsLinkLocal())
       
 11552                         flags |= KRouteAdd_ISROUTER;
       
 11553                     else
       
 11554                         goto drop_packet;
       
 11555                     }
       
 11556                 // Create host route for the target
       
 11557                 (void)GetRoute(aNd.iHdr->iRD.Target(), 128, flags, &target_link);
       
 11558                 if (flags & KRouteAdd_ISROUTER)
       
 11559                     {
       
 11560                     // Target is a router, need to add redirect route for the destination,
       
 11561                     // pointing to the gateway (= target).
       
 11562                     TInetAddr gateway;
       
 11563                     gateway.SetAddress(target);
       
 11564                     (void)GetRoute(aNd.iHdr->iRD.Destination(), 128, CIp6Route::ERedirect, &gateway);
       
 11565                     }
       
 11566                 //
       
 11567                 // Previously, any flow using the rerouted destination address was assigned
       
 11568                 // to the 'route'. Need to kick those flows to recheck their nexthop (e.g.
       
 11569                 // all flows going to the 'destination' must now be assigned to the new
       
 11570                 // redirected route
       
 11571                 // Note: this may be bad thing, if there are many redirects and many unaffected
       
 11572                 // flows are attached to the 'route' (which could be the default route).
       
 11573                 // - more intelligent SetChanged(new_route), wich only affect the flows that have
       
 11574                 //   a better match with the new route (the redirect), or
       
 11575                 // - change of logic and implement true "destination cache" (flow send would have
       
 11576                 //   to look into it for every packet) [or, view flows themselves as "destination
       
 11577                 //   cache"?]
       
 11578                 // -- msa
       
 11579                 route->SetChanged();
       
 11580                 }
       
 11581             else
       
 11582                 {
       
 11583                 LOG(Log::Printf(_L("\tIF %u [%S] Redirect [%S] to [%S] rejected"), iScope[0], &iName, &tmpdst, &tmpsrc));
       
 11584                 goto drop_packet;
       
 11585                 }
       
 11586             }
       
 11587             break;
       
 11588         default:
       
 11589             break;
       
 11590         }
       
 11591     //
       
 11592     //
       
 11593     if (notify)
       
 11594         {
       
 11595         NotifyFlows(EFlow_READY);
       
 11596         Interfacer().ScanHoldings();
       
 11597         }
       
 11598     
       
 11599 #ifdef SYMBIAN_TCPIPDHCP_UPDATE
       
 11600     //RFC-5006 Changes
       
 11601     if (iRdnssList!=NULL)
       
 11602         {
       
 11603         if(iRdnssList->GetRdnssFlag())      
       
 11604             {
       
 11605             // DNS information changed
       
 11606             NotifyInterfaceEvent(EventTypeModify);
       
 11607             }
       
 11608         }
       
 11609 #else
       
 11610     if (dns_flag)
       
 11611         {
       
 11612         // DNS information changed
       
 11613         NotifyInterfaceEvent(EventTypeModify);
       
 11614         }
       
 11615 #endif // SYMBIAN_TCPIPDHCP_UPDATE
       
 11616 
       
 11617     return 0;
       
 11618     //
       
 11619     // Drop packets (should only be used for obviously bad packets)
       
 11620     //
       
 11621 drop_packet:
       
 11622     aPacket.Free();
       
 11623     return -1;
       
 11624     }
       
 11625 
       
 11626 
       
 11627 #ifdef ARP
       
 11628 //
       
 11629 // CIp6Manager::ArpHandler
       
 11630 // ***********************
       
 11631 /**
       
 11632 // Receives all ARP packets
       
 11633 //
       
 11634 // Currently always "consumes" packet,
       
 11635 // and return is always < 0
       
 11636 */
       
 11637 TInt CIp6Manager::ArpHandler(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo)
       
 11638     {
       
 11639     TInet6Packet<TInet6HeaderArp> arp(aPacket);
       
 11640     for (;;)
       
 11641         {
       
 11642         if (arp.iHdr == NULL)
       
 11643             break;      // Too short, ignore!
       
 11644         // Remap with real packet length, and assume all of the
       
 11645         // ARP packet will fit into single RMBuf. Should be okay,
       
 11646         // as only IPv4 is being implemented and map will only
       
 11647         // fail if hwaddr length is > 56 bytes! Computed by
       
 11648         // RMBuf = 128 bytes, prlen = 4 for IPv4, fixed part is
       
 11649         // 8 bytes => (128 - 8 - 2*prlen) / 2 = 56. For longer
       
 11650         // than 56 hwaddr, this ARP stops working!  -- msa
       
 11651         arp.Set(aPacket, 0, arp.iHdr->HeaderLength());
       
 11652         if (arp.iHdr == NULL)
       
 11653             break;      // Too short (corrupt packet, or hwlen > 56)
       
 11654         if (arp.iHdr->PrAddrLen() != 4 ||
       
 11655             arp.iHdr->ProtocolType() != KArpProtocolType_IP)
       
 11656             break;      // Only IPv4 supported.
       
 11657         CIp6Interface *const srcif = FindInterface(aInfo.iInterfaceIndex);
       
 11658         if (!srcif)
       
 11659             break;      // Cannot find interface...
       
 11660         (void)srcif->ArpHandler(aPacket, aInfo, arp);
       
 11661         break;      // Alway exit the loop!
       
 11662         }
       
 11663     //
       
 11664     // Packet always consumed, whether processed or not!
       
 11665     //
       
 11666     aPacket.Free();
       
 11667     if (iScanHolding)
       
 11668         ScanHoldings();
       
 11669     return -1;
       
 11670     }
       
 11671 
       
 11672 TInt CIp6Interface::ArpHandler(RMBufRecvPacket &aPacket, RMBufRecvInfo &aInfo, TInet6Packet<TInet6HeaderArp> &aArp)
       
 11673     {
       
 11674     if (iHwAddr.GetUserLen() != aArp.iHdr->HwAddrLen())
       
 11675         return 0;   // Hardware address length does not match the interface, ignore ARP!
       
 11676     if (aArp.iHdr->PrAddrLen() != 4)
       
 11677         return 0;   // Protocol address is IPv4, must be 4 bytes long!
       
 11678     const TUint operation = aArp.iHdr->Operation();
       
 11679     if (operation != EArpOperation_REQUEST && operation != EArpOperation_REPLY)
       
 11680         return 0;   // Only the basic REQUEST/REPLY are supported!
       
 11681 
       
 11682     TIp46Addr sender(0), target(0);
       
 11683     TPtr8(&sender.u.iAddr8[12], 4).Copy(aArp.iHdr->SenderPrAddr());
       
 11684     TPtr8(&target.u.iAddr8[12], 4).Copy(aArp.iHdr->TargetPrAddr());
       
 11685 
       
 11686     TLinkAddr sender_link, target_link;
       
 11687     sender_link.SetFamily(iHwAddr.Family());
       
 11688     target_link.SetFamily(iHwAddr.Family());
       
 11689     sender_link.SetAddress(aArp.iHdr->SenderHwAddr());
       
 11690     target_link.SetAddress(aArp.iHdr->TargetHwAddr());
       
 11691 #ifdef _LOG
       
 11692         {
       
 11693         TLogAddressPrefix link(TInetAddr::Cast(sender_link));
       
 11694         TLogAddressPrefix ip(sender);
       
 11695         Log::Printf(_L("\tIF %u [%S] ARP (bytes=%d) sender=%S [%S]"), iScope[0], &iName, aInfo.iLength, &ip, &link);
       
 11696         link.Set(target_link);
       
 11697         ip.Set(target);
       
 11698         Log::Printf(_L("\t\tTarget=%S [%S]"), &ip, &link);
       
 11699         }
       
 11700 #endif
       
 11701     if (sender_link.Address() == iHwAddr.Address())
       
 11702         {
       
 11703         // The sender has my hardware address. This may happen because
       
 11704         // 1) this is my own ARP echoed back from the link for some reason
       
 11705         // 2) someone else on the link has the same link layer address
       
 11706         // In either case, there is not much that can be done, just drop
       
 11707         // the ARP for now...
       
 11708         LOG(Log::Printf(_L("\t\tARP sender link is my hwaddr, ARP ignored")));
       
 11709         return 0;
       
 11710         }
       
 11711     //
       
 11712     // Assume IPv4 addressess are stored as 128 bit ids (e.g. iPrefix == 0)
       
 11713     // (thus it is sufficient to check the id)
       
 11714     //
       
 11715     TIp6AddressInfo *my_id = IsMyId(target);
       
 11716     if (my_id && my_id->iPrefix != 0)
       
 11717         my_id = NULL;   // ignore other matches
       
 11718 
       
 11719     // DAD stuff
       
 11720     // *********
       
 11721     // ..if sender matches tentative => declare collision on sender_id
       
 11722     // ..if sender matches my address => declare nasty collision on sender_id
       
 11723     // ..if sender is 0.0.0.0 and target matches tentative => declare collision on my_id
       
 11724     //
       
 11725     TIp6AddressInfo *dup_id = IsMyId(sender);
       
 11726     if (dup_id && dup_id->iPrefix != 0)
       
 11727         dup_id = NULL;
       
 11728 
       
 11729     if (my_id && my_id->IsTentative())
       
 11730         {
       
 11731         if (sender.u.iAddr32[3] == 0)
       
 11732             {
       
 11733             // If sender = None, it couldn't have been found as duplicate!
       
 11734             ASSERT(dup_id == NULL);
       
 11735             dup_id = my_id;
       
 11736             }
       
 11737         my_id = NULL;   // Anyways, it's not yet my official address, do not reply!
       
 11738         } 
       
 11739     TBool gratuitousArpFromOtherHost = EFalse;
       
 11740     TBool defendIPAddress = EFalse;
       
 11741     if (dup_id)
       
 11742         {
       
 11743         if (aArp.iHdr->SenderHwAddr() !=  iHwAddr.Address() && operation == EArpOperation_REQUEST)
       
 11744                  gratuitousArpFromOtherHost = ETrue;
       
 11745         DuplicateAddress(dup_id, defendIPAddress, gratuitousArpFromOtherHost);
       
 11746         if(!defendIPAddress)    
       
 11747             return 0;       
       
 11748         }
       
 11749 
       
 11750     if(!defendIPAddress)
       
 11751     {
       
 11752     //
       
 11753     // Choose Flags, if target==me, force creation of the entry
       
 11754     //
       
 11755     const TInt flags = KRouteAdd_OVERRIDE |
       
 11756         ((my_id != NULL) ?
       
 11757         (operation == EArpOperation_REPLY ? KRouteAdd_SOLICITED : 0) :
       
 11758         KRouteAdd_UPDATEONLY);
       
 11759 
       
 11760     // Update neighbor cache only if sender IP address is defined
       
 11761     if (sender.u.iAddr32[3])
       
 11762         (void)GetRoute(sender, 128, flags, &sender_link);
       
 11763     }
       
 11764 
       
 11765     // If target was me and operation is a Request, swap sender and target
       
 11766     // and fill in my hw address.
       
 11767     if ((my_id || defendIPAddress) && operation == EArpOperation_REQUEST)
       
 11768         {
       
 11769         if(defendIPAddress)
       
 11770         {
       
 11771         aArp.iHdr->TargetHwAddr().Copy(iHwAddr.Address());
       
 11772         }
       
 11773         else 
       
 11774         {
       
 11775         aArp.iHdr->TargetHwAddr().Copy(aArp.iHdr->SenderHwAddr()); 
       
 11776         }
       
 11777         aArp.iHdr->TargetPrAddr().Copy(aArp.iHdr->SenderPrAddr());
       
 11778         aArp.iHdr->SenderHwAddr().Copy(iHwAddr.Address());
       
 11779         aArp.iHdr->SenderPrAddr().Copy(TPtrC8(&target.u.iAddr8[12], 4));
       
 11780         aArp.iHdr->SetOperation(EArpOperation_REPLY);
       
 11781         aInfo.iProtocol = KProtocolArp;
       
 11782 
       
 11783         // draft-ietf-zeroconf-ipv4-linklocal-05.txt says that whenever
       
 11784         // the sender is ipv4 link local, then the replies (and requests)
       
 11785         // must always be sent to the broadcast address [IMHO, this is
       
 11786         // a bit dubious rule, but if it is so specified, comply... -- msa]
       
 11787         if (target.Scope() == KIp6AddrScopeLinkLocal)
       
 11788             {
       
 11789             TInetAddr::Cast(aInfo.iDstAddr).SetAddress(KInetAddrBroadcast);
       
 11790             aInfo.iFlags = KIpBroadcastOnLink;  // Dst is broadcast.
       
 11791             }
       
 11792         else
       
 11793             {
       
 11794             aInfo.iDstAddr = sender_link;
       
 11795             aInfo.iFlags = 0;                   // Dst is unicast hw address.
       
 11796             }
       
 11797         if (iNifIf)
       
 11798             {
       
 11799             aPacket.Pack();
       
 11800             iNifIf->Send(aPacket, NULL);
       
 11801             }
       
 11802         }
       
 11803     return 0;
       
 11804     }
       
 11805 
       
 11806 #endif
       
 11807 
       
 11808 
       
 11809 // CIp6Interface::Ip4RedirectHandler
       
 11810 // *********************************
       
 11811 /**
       
 11812 // Handle IPv4 Redirect ICMP
       
 11813 //
       
 11814 // @param   aPacket the returned ICMP error packet
       
 11815 // @param   aInfo   the associated info (iIcmp != 0)
       
 11816 */
       
 11817 void CIp6Interface::Ip4RedirectHandler(const RMBufRecvPacket &aPacket, const RMBufRecvInfo &aInfo)
       
 11818     {
       
 11819     // Because IPv4 ICMP redirect is catched from the ICMP Error handling
       
 11820     // path, the info block is already loaded with the data extracted from
       
 11821     // from ICMP error message as follows:
       
 11822     //
       
 11823     // - aInfo.iParemeter == Gateway address (IPv4 in host byteorder)
       
 11824     // - aInfo.iSrcAddr == should be my address of the original packet
       
 11825     // - aInfo.iDstAddr == should be the destination of the original packet
       
 11826     //
       
 11827     // Handle all redirects (codes 0-3) as host redirects (ignore other codes)
       
 11828     if (aInfo.iCode > 3)
       
 11829         return;
       
 11830 
       
 11831     const TIp46Addr gateway(aInfo.iParameter);
       
 11832     const TIp6Addr &dst_addr = TInetAddr::Cast(aInfo.iDstAddr).Ip6Address();
       
 11833 
       
 11834     //
       
 11835     // Check various things, whether to actually accept the redirect
       
 11836     //
       
 11837     // .. did I send this packet?
       
 11838     if (!IsMyAddress(TInetAddr::Cast(aInfo.iSrcAddr).Ip6Address()))
       
 11839         return; // -- original source is not my address, just ignore the redirect
       
 11840 
       
 11841     // ..the gateway must be another node on the link
       
 11842     CIp6Route *route = FindRoute(gateway, NULL);
       
 11843     if (route == NULL || !(route->IsOnlink() || route->IsHostRoute()))
       
 11844         return;
       
 11845 
       
 11846     // ...check that destination would actually have been sent to the
       
 11847     // ...router that sent the ICMP redirect.
       
 11848     const TUint dstType = dst_addr.Scope()-1;
       
 11849     if (dstType > EScopeType_NET)
       
 11850         return; // -- bad scope value
       
 11851     route = Interfacer().FindRoute(dst_addr, iScope[dstType], dstType);
       
 11852     if (route == NULL || &route->iInterface != this || !route->IsGateway())
       
 11853         return; // -- nope, not routed to a gateway on this interface
       
 11854     const TIpHeader *const ip = ((RMBufPacketPeek &)aPacket).GetIpHeader();
       
 11855     if (!ip || ip->ip4.Version() != 4)
       
 11856         return; // -- probably bad packet
       
 11857     if (!TIp46Addr(ip->ip4.SrcAddr()).IsEqual(route->iAddress.Ip6Address()))
       
 11858         return; // -- would not be sent to source of the icmp redirect
       
 11859 
       
 11860     //
       
 11861     // Redirect accepted, do the stuff...
       
 11862     //
       
 11863     (void)GetRoute(gateway, 128, KRouteAdd_ISROUTER);   // Must mark the gateway as ROUTER!
       
 11864     const TInetAddr gw(gateway, 0);
       
 11865     (void)GetRoute(dst_addr, 128, CIp6Route::ERedirect, &gw);
       
 11866 #ifdef _LOG
       
 11867         {
       
 11868         TBuf<70> tmpdst, tmpgw;
       
 11869         TInetAddr::Cast(aInfo.iDstAddr).OutputWithScope(tmpdst);
       
 11870         gw.OutputWithScope(tmpgw);
       
 11871         Log::Printf(_L("\tIF %u [%S] Redirecting IPv4 dst=[%S] to [%S]"), iScope[0], &iName, &tmpdst, &tmpgw);
       
 11872         }
       
 11873 #endif
       
 11874     // Previously, any flow using the rerouted destination address was assigned
       
 11875     // to the 'route'. Need to kick those flows to recheck their nexthop (e.g.
       
 11876     // all flows going to the 'destination' must now be assigned to the new
       
 11877     // redirected route
       
 11878     route->SetChanged();
       
 11879     }
       
 11880 
       
 11881 //
       
 11882 // ********************************
       
 11883 // MIfUser Interface Implementation
       
 11884 // ********************************
       
 11885 //
       
 11886 
       
 11887 /**
       
 11888 //  The NIF::BindL failed.
       
 11889 //
       
 11890 //  A relic from ancient time -- not used currently.
       
 11891 //
       
 11892 //  @deprecated
       
 11893 */
       
 11894 void CIp6NifUser::IfUserBindFailure(TInt aResult, TAny* aId)
       
 11895     {
       
 11896     LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserBindFailure(%d, %d)"), &LogName(), aResult, (TInt)aId));
       
 11897 
       
 11898     // Remove warnings
       
 11899     (void) aResult;
       
 11900     (void) aId;
       
 11901     }
       
 11902 
       
 11903 /**
       
 11904 // Introduce a new interface.
       
 11905 //
       
 11906 // @param aIf   The NIF
       
 11907 // @param aId   A relic from history -- not used currently.
       
 11908 */
       
 11909 void CIp6NifUser::IfUserNewInterfaceL(CNifIfBase* aIf, TAny* aId)
       
 11910     {
       
 11911     (void) aId;     // Remove warning
       
 11912 
       
 11913     LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserNewInterface(%d, %d)"), &LogName(), (TInt)aIf, (TInt)aId));
       
 11914     if (!aIf)
       
 11915         return;     // Should do something? Does this ever happen?
       
 11916     TNifIfInfo info;
       
 11917     aIf->Info(info);
       
 11918     CIp6Interface *iface = iManager.GetInterfaceByNameL(info.iName);
       
 11919     if (iface->IsNetdial())
       
 11920         User::Leave(KErrBadDriver); // Interface is giving bad name ('')
       
 11921 
       
 11922     LOG(Log::Printf(_L("CIp6NifUser[%S]::AddInterface(CIp6Interface[%S])"), &LogName(), &iface->iName));
       
 11923     aIf->Open();    // Prevent aIf from being deleted while in DoBind.
       
 11924     (void)iface->DoBind(this, aIf);
       
 11925     aIf->Close();   // *NOTE* This will delete the CNifIfBase instance
       
 11926                     // if there was no other references to it!
       
 11927     }
       
 11928     
       
 11929 /**
       
 11930 // Reports closed interface using negative error code
       
 11931 // Reports status of operable interface using positive status code
       
 11932 //
       
 11933 // @param aResult Error code of closed interface or status of operable interface
       
 11934 // @param aIf The NIF
       
 11935 */
       
 11936 void CIp6NifUser::IfUserInterfaceDown(TInt aResult, CNifIfBase* aIf)
       
 11937     {
       
 11938 
       
 11939     CIp6Interface *const iface = iManager.FindInterface(aIf);
       
 11940     //
       
 11941     // IfUserInterfaceDown can only be processed, if the stack has an
       
 11942     // instance of CIp6Interface that is actually connected to the aIf
       
 11943     // (IfUserNewInterface has been called for it!). The above find
       
 11944     // returns non-NULL iface only iff  "iface->iNifIf == aIf".
       
 11945     //
       
 11946     if (iface == NULL)
       
 11947         {
       
 11948         // NIFMAN is reporting interface down, which has no
       
 11949         // corresponding instance within the stack -- ignore
       
 11950         // silently... [this may happen if interface has been
       
 11951         // deleted from the stack, for example via ifconfig
       
 11952         // socket options]
       
 11953         LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserInterfaceDown(%d, %d) NOT FOUND"), &LogName(), aResult, (TInt)aIf));
       
 11954         return;
       
 11955         }
       
 11956     LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserInterfaceDown(%d, %d) is CIp6Interface[%S])"), &LogName(), aResult, (TInt)aIf, &iface->iName));
       
 11957 
       
 11958     const TInt link_change = (aResult == KErrLinkConfigChanged);
       
 11959     if (!link_change && aResult <= 0)
       
 11960         {
       
 11961         // First notify the error state to all flows attached to
       
 11962         // this interface. This will affect all flows that don't
       
 11963         // the flag iNoInterfaceError set.
       
 11964         iface->NotifyFlows(aResult);
       
 11965         }
       
 11966     else if (aResult > 0)
       
 11967         {
       
 11968         // IfUserInterfaceDown positive values are used to report NIF events to stack.
       
 11969         switch (aResult)
       
 11970             {
       
 11971             case KLinkLayerOpen:
       
 11972                 if (iface->iIsSuspended)
       
 11973                     {
       
 11974                     // Flip flows to trigger CanSend()
       
 11975                     iface->NotifyFlows(EFlow_HOLD, ETrue);
       
 11976                     iface->NotifyFlows(EFlow_READY, ETrue);
       
 11977                     iface->iIsSuspended = FALSE;
       
 11978                     }
       
 11979             break;
       
 11980             case KDataTransferTemporarilyBlocked:
       
 11981                 iface->iIsSuspended = TRUE;
       
 11982             break;
       
 11983             }
       
 11984         // Just return here when processing positive values
       
 11985         return;
       
 11986         }
       
 11987     // Note: if there is no holding route, flows will be terminated
       
 11988     // by the Reset(). Currently, holding *should* always exist.
       
 11989     for (CIp6Route *rt = iface->iRouteList; rt != NULL; rt = rt->iNext)
       
 11990         Interfacer().MoveToHolding(*rt);
       
 11991 
       
 11992     if(link_change)
       
 11993         {
       
 11994         // In case link is changed, just reset the interface but do not delete it.
       
 11995         iface->Reset(link_change);
       
 11996         }
       
 11997     else
       
 11998         {
       
 11999         // Delete interface instance when it goes down.
       
 12000         Interfacer().RemoveInterface(iface);
       
 12001         }
       
 12002 
       
 12003     if (iNetwork)
       
 12004         iNetwork->Protocol()->Error(aResult, NULL);
       
 12005     }
       
 12006 
       
 12007 void CIp6NifUser::IfUserOpenNetworkLayer()
       
 12008     {
       
 12009     LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserOpenNetworkLayer()"), &LogName()));
       
 12010     __ASSERT_ALWAYS(iNetwork, User::Invariant());
       
 12011     iNetwork->Protocol()->Open();
       
 12012     iManager.iNifCount++;
       
 12013     iManager.IncUsers();
       
 12014     }
       
 12015 
       
 12016 void CIp6NifUser::IfUserCloseNetworkLayer()
       
 12017     {
       
 12018     LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserCloseNetworkLayer()"), &LogName()));
       
 12019     __ASSERT_ALWAYS(iNetwork, User::Invariant());
       
 12020     --iManager.iNifCount;
       
 12021     iManager.DecUsers();
       
 12022     iNetwork->Protocol()->Close();
       
 12023     }
       
 12024 
       
 12025 CProtocolBase* CIp6NifUser::IfUserProtocol()
       
 12026     {
       
 12027     LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserProtocol() --> %d"), &LogName(), (TInt)iNetwork));
       
 12028     return iNetwork ? iNetwork->Protocol() : NULL;
       
 12029     }
       
 12030 
       
 12031 TBool CIp6NifUser::IfUserIsNetworkLayerActive()
       
 12032     {
       
 12033     LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserIsNetworkLayerActive() iUsers=%d, iNifCount=%d --> %d"),
       
 12034         &LogName(), iManager.iUsers, iManager.iNifCount, (iManager.iUsers - iManager.iNifCount) > 0));
       
 12035     return (iManager.iUsers - iManager.iNifCount) > 0;
       
 12036     }
       
 12037 
       
 12038 TBool CIp6NifUser::IfUserIsNetworkLayerActive(CNifIfBase *aIf)
       
 12039     {
       
 12040     if (aIf == NULL)
       
 12041         {
       
 12042         LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserIsNetworkLayerActive(NULL) *BUG IN NIFMAN* "), &LogName()));
       
 12043         return IfUserIsNetworkLayerActive();
       
 12044         }
       
 12045     CIp6Interface *const iface = iManager.FindInterface(aIf);
       
 12046     if (iface == NULL)
       
 12047         {
       
 12048         LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserIsNetworkLayerActive(%d) *BUG IN NIFMAN"), &LogName(), (TInt)aIf));
       
 12049         return IfUserIsNetworkLayerActive();
       
 12050         }
       
 12051     LOG(Log::Printf(_L("CIp6NifUser[%S]::IfUserIsNetworkLayerActive(%S) returns %d"),
       
 12052         &LogName(), &iface->iName, iface->iFlows > 0));
       
 12053     return iface->iFlows > 0;
       
 12054     }
       
 12055 #ifdef SYMBIAN_TCPIPDHCP_UPDATE  
       
 12056 /**
       
 12057 // Do DAD for my blobal address
       
 12058 // Ref: RFC 4862
       
 12059 // @param aPrefix The prefix of an IP address,part of prefix information sent by RA
       
 12060 // @param aLength The prefix length,part of prefix information sent by RA
       
 12061 */
       
 12062 void CIp6Interface::PerformDADForGlobalAddress(const TIp6Addr &aPrefix,const TUint aLength)
       
 12063     {
       
 12064     #ifdef _DEBUG
       
 12065         LOG(Log::Printf(_L("\tCIp6Interface::PerformDADForGlobalAddress is called")));
       
 12066     #endif
       
 12067     if (&aPrefix == NULL)
       
 12068             return;
       
 12069     
       
 12070     TInetAddressInfo info;
       
 12071     info.iAddress = aPrefix;
       
 12072     MakeFullAddress(info.iAddress, aLength,iAddress.iId.u.iAddr8, sizeof(iAddress.iId.u.iAddr8));
       
 12073     #ifdef _DEBUG
       
 12074         LOG(Log::Printf(_L("\tCIp6Interface::PerformDADForGlobalAddress,MakeFullAddress done")));
       
 12075     #endif
       
 12076     TIp6AddressInfo *address;
       
 12077     // check info.iAddress matches any of the id's for the interface (also tentative ones!)
       
 12078     address = IsMyId(info.iAddress);
       
 12079     if(address == NULL)
       
 12080         {
       
 12081         #ifdef _DEBUG
       
 12082             LOG(Log::Printf(_L("\tCIp6Interface::PerformDADForGlobalAddress,address is NULL so returning from the method")));
       
 12083         #endif  
       
 12084         return;
       
 12085         }
       
 12086     if (!address->IsTentative())
       
 12087         {
       
 12088         #ifdef _DEBUG
       
 12089             LOG(Log::Printf(_L("\tCIp6Interface::PerformDADForGlobalAddress,sending NS")));
       
 12090         #endif  
       
 12091         SendNeighbors(KInet6ICMP_NeighborSol, NULL,info.iAddress,&KInet6AddrNone);
       
 12092         }
       
 12093     else
       
 12094         {
       
 12095         //it is not my address ignore it
       
 12096         #ifdef _DEBUG
       
 12097             LOG(Log::Printf(_L("\tCIp6Interface::PerformDADForGlobalAddress,address->IsTentative()")));
       
 12098         #endif
       
 12099         return;
       
 12100         }
       
 12101     }
       
 12102 #endif // SYMBIAN_TCPIPDHCP_UPDATE  
       
 12103 
       
 12104 #ifdef __ARMCC__
       
 12105 #pragma pop
       
 12106 #endif