networkprotocols/tcpipv4v6prt/src/in_trans.cpp
changeset 0 af10295192d8
child 13 343eee2d4450
child 18 39bb7c3571e9
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2006-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 // in_trans.cpp - transport layer protocol base
       
    15 //
       
    16 
       
    17 #include "in_trans.h"
       
    18 #include "inet6log.h"
       
    19 
       
    20 #include <e32math.h>
       
    21 #include <comms-infras/nifif_internal.h>
       
    22 
       
    23 // speed optimisations
       
    24 #ifdef __ARMCC__
       
    25 #pragma push
       
    26 #pragma arm
       
    27 #endif
       
    28 
       
    29 #define SYMBIAN_NETWORKING_UPS
       
    30 
       
    31 CProtocolInet6Transport::CProtocolInet6Transport()
       
    32 	{
       
    33 	// Initialize random seed value
       
    34 	TTime  currentTime;
       
    35 	currentTime.HomeTime();
       
    36 	iSeed = currentTime.Int64() + User::TickCount();
       
    37 	}
       
    38 
       
    39 
       
    40 void CProtocolInet6Transport::InitL(TDesC& aTag)
       
    41 	{
       
    42 	CProtocolInet6Base::InitL(aTag);
       
    43 	}
       
    44 
       
    45 
       
    46 void CProtocolInet6Transport::StartL()
       
    47 	{
       
    48 	CProtocolInet6Base::StartL();
       
    49 	}
       
    50 
       
    51 
       
    52 CProtocolInet6Transport::~CProtocolInet6Transport()
       
    53 	{
       
    54 	}
       
    55 
       
    56 
       
    57 TInt CProtocolInet6Transport::Send(RMBufChain& /*aPacket*/,CProtocolBase* /*aSourceProtocol=NULL*/)
       
    58 	{
       
    59 	Panic(EInet6Panic_NotSupported);
       
    60 	return 0;
       
    61 	}
       
    62 
       
    63 
       
    64 //
       
    65 // Bind request from a protocol above us
       
    66 //
       
    67 void CProtocolInet6Transport::BindL(CProtocolBase* /*aProtocol*/, TUint /*aId*/)
       
    68 	{
       
    69 	Panic(EInet6Panic_NotSupported);
       
    70 	}
       
    71 
       
    72 
       
    73 //
       
    74 // Find SAP based on end-point addresses.
       
    75 //
       
    76 // This routine is rather involved, because it is used for a number of different
       
    77 // purposes. The routine returns a "best match" socket provider based on source
       
    78 // and destination socket addresses (IP address & port), or NULL if no mathing
       
    79 // provider is found (see below for an explanation on how matches are ranked).
       
    80 //
       
    81 // The method supports the following forms:
       
    82 //
       
    83 //  o LocateProvider(minimum rank, local socket address);  or
       
    84 //    LocateProvider(minimum rank, local socket address, unspecified socket address);
       
    85 //
       
    86 //    This form is used when binding a socket in order to check that the port is
       
    87 //    not already in use. At least local port must be specified. Local address
       
    88 //    may be unspecified.  The first provider that matches the local port (and
       
    89 //    local address, if given) is returned.
       
    90 //
       
    91 //  o LocateProvider(minimum rank, local socket address, remote socket address);
       
    92 //
       
    93 //    This form is used in order to locate the correct socket provider, when
       
    94 //    a transport PDU has been received. For this use, the complete local
       
    95 //    and remote addresses must be specified.
       
    96 //
       
    97 //    Another use of this form is to verify the uniqueness of the source/destination
       
    98 //    socket address pair when creating a new connection. This is only an issue if
       
    99 //    the source port has been explicitly bound and local address reuse has been enabled.
       
   100 //    In this case, the destination socket address MUST be unique among all connections
       
   101 //    terminating in the same local socket address.
       
   102 //
       
   103 //    Note: for the latter use, local IP address may be left unspecified. In this case,
       
   104 //    it matches all addresses. Local port is mandatory.
       
   105 //
       
   106 //  The minimum rank parameter specifies the minimum acceptable accuracy of the match.
       
   107 //  The the match with the highest rank found is returned, or NULL if no match of
       
   108 //  at least the requested rank is found.
       
   109 //
       
   110 //  Matches are ranked as follows (highest rank first):
       
   111 //
       
   112 //   EMatchExact or EMatchConnection:
       
   113 //
       
   114 //        Both local and remote socket addresses match. Local IP address may be
       
   115 //        unspecified, if the connection is waiting for a flow to become ready.
       
   116 //
       
   117 //        This rank is only relevant if caller specified a remote address.
       
   118 //        The returned socket provider handles a connected socket.
       
   119 //
       
   120 //   EMatchServerSpecAddr:
       
   121 //
       
   122 //        Local socket address matches and remote socket address is unspecified.
       
   123 //
       
   124 //        This means that the returned socket provider handles a server socket
       
   125 //        that has been bound to a specific local address.
       
   126 //
       
   127 //   EMatchServerUnspecAddr:
       
   128 //
       
   129 //        Local port matches. Local IP address is unspecified. Remote socket address
       
   130 //        is unspecified.
       
   131 //
       
   132 //        This means that the returned socket provider handles a server socket
       
   133 //        that has been bound to an unspecified address.
       
   134 //
       
   135 //   EMatchLocalPort:
       
   136 //
       
   137 //        Local port must match. Local IP address or remote socket address are not tested.
       
   138 //
       
   139 //        This means that the returned socket provider will conflict with an attempted
       
   140 //        bind() if the KSoReuseAddr socket option is not used.
       
   141 //
       
   142 #ifndef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
   143 CProviderInet6Transport* CProtocolInet6Transport::LocateSap(TProviderMatchEnum aRank, TUint aFamily, 
       
   144 const TInetAddr& aLocalAddr, const TInetAddr& aRemoteAddr, CProviderInet6Base *aSap)
       
   145 #else
       
   146 CProviderInet6Transport* CProtocolInet6Transport::LocateSap(TProviderMatchEnum aRank, TUint aFamily,
       
   147 		const TInetAddr& aLocalAddr, const TInetAddr& aRemoteAddr, CProviderInet6Base *aSap,
       
   148 		TUint32 aSourceIfIndex)
       
   149 #endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
   150 	{
       
   151 	ASSERT(aLocalAddr.Port() != KInetPortNone);
       
   152 
       
   153 	CProviderInet6Transport *sapFound = NULL, *sap;
       
   154 	TUint port = aLocalAddr.Port();
       
   155 	TProviderMatchEnum rank = (TProviderMatchEnum)(aRank-1);
       
   156 
       
   157 	// CProtocolInet6Base::LocateProvider() puts us into the right hashed queue.
       
   158 	for (sap = (CProviderInet6Transport *)(aSap != NULL ? aSap : CProtocolInet6Base::LocateProvider(port));
       
   159 			sap != NULL; sap = (CProviderInet6Transport *)sap->iNextSAP)
       
   160 		{
       
   161 		// If aSap non-NULL, return first match
       
   162 		if (aSap != NULL && rank >= aRank)
       
   163 			break;
       
   164 
       
   165 		const TInetAddr& local = sap->iFlow.FlowContext()->LocalAddr();
       
   166 		if (port != local.Port())
       
   167 			continue;
       
   168 #ifdef SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
   169         // In case of loopback no need to lock interface
       
   170 		if(!aLocalAddr.IsLoopback())
       
   171 		    {	
       
   172 		    // Port matches this SAP, so if this SAP has an interface that it is
       
   173 		    // locked to, confirm the inbound packet is on that interface. That is,
       
   174 		    // if the SAP is locked to an interface, this code ensures that the
       
   175 		    // packet is only accepted if it is coming over the same interface
       
   176 		    // that the SAP is locked to.
       
   177 		    TScopeType scoping = sap->iFlow.FlowContext()->LockType();
       
   178 		    TUint32 interfaceNum = sap->iFlow.FlowContext()->LockId();
       
   179 		
       
   180 		    // Check that the source interface index was supplied. Also check for lock id > 0.
       
   181 		    // If lock id > 0 this implies that the interface is locked down for this SAP. Also
       
   182 		    // ignore the magic value lock id of KNetworkIdFromAddress.
       
   183 		    if ((aSourceIfIndex > 0) && (interfaceNum > 0) && (interfaceNum != KNetworkIdFromAddress))
       
   184 			    {
       
   185 			    // The sap currently being checked is locked to an interface. Check to
       
   186 			    // see what type of lock (scoping) it is.
       
   187 			    if (scoping == EScopeType_IF)
       
   188 			   	    {
       
   189 			   	    // This sap is locked to EScopeType_IF
       
   190 	                if (interfaceNum != aSourceIfIndex)
       
   191 	            	    {
       
   192 	            	    // Not the right interface, go to next SAP
       
   193 	                    continue;
       
   194 	                    }
       
   195             	    }
       
   196 			    else 
       
   197 				    {
       
   198 				    // Not locked to EScopeType_IF, so now need the network ID and IAP number from the
       
   199 				    // interface, to check against one of those. Fetch this from the source interface
       
   200 				    // based on the interface index.
       
   201 				    const MInterface* iface = sap->iFlow.FlowContext()->Interfacer()->Interface(aSourceIfIndex);
       
   202 				    if (iface)
       
   203 					    {
       
   204 					    if (scoping == EScopeType_IAP)
       
   205 						    {
       
   206 						    // This sap is locked to EScopeType_IAP. Check if the source interface
       
   207 						    // is over the same IAP.
       
   208 						    TUint id = iface->Scope(EScopeType_IAP);
       
   209 						    if (id != interfaceNum)
       
   210 							    {
       
   211 							    // IAP does not match that required
       
   212 							    continue;  
       
   213 							    } 							
       
   214 						    }
       
   215 					    else if (scoping == EScopeType_NET )
       
   216 						    { 
       
   217 						    // This sap is locked to EScopeType_NET. Check if the source interface
       
   218 						    // is over the same network ID.
       
   219 						    TUint id = iface->Scope(EScopeType_NET);
       
   220 						    if (id != interfaceNum) 
       
   221 							    {
       
   222 							    // Network ID does not match that required
       
   223 							    continue;    
       
   224 							    }
       
   225 						    }
       
   226 					    }
       
   227 				    }
       
   228 			    }
       
   229 			}
       
   230 #endif //SYMBIAN_STRICT_EXPLICIT_SOCKET_BINDING
       
   231 		
       
   232 		const CFlowContext *const flow = sap->iFlow.FlowContext();
       
   233 
       
   234 		TBool localMatch = aLocalAddr.CmpAddr(local) &&
       
   235 			(aLocalAddr.Scope() == 0 || aLocalAddr.Scope() == local.Scope());
       
   236 		if (!sap->iSockFlags.iAddressSet || localMatch)
       
   237 			{
       
   238 			if (sap->iSockFlags.iConnected)
       
   239 				{
       
   240 				if (localMatch && aRemoteAddr.CmpAddr(flow->RemoteAddr())
       
   241 					&& (aRemoteAddr.Scope() == 0 || aRemoteAddr.Scope() == flow->RemoteAddr().Scope()))
       
   242 					{
       
   243 					rank = EMatchExact;
       
   244 					sapFound = sap;
       
   245 					break;
       
   246 					}
       
   247 				}
       
   248 			else
       
   249 				{
       
   250 				if (rank >= EMatchServerSpecAddr)
       
   251 					continue;
       
   252 
       
   253 				if (localMatch)
       
   254 					{
       
   255 					rank = EMatchServerSpecAddr;
       
   256 					sapFound = sap;
       
   257 					continue;
       
   258 					}
       
   259 
       
   260 				if (rank >= EMatchServerUnspecAddr)
       
   261 					continue;
       
   262 
       
   263 				if (sap->iSockFamily == aFamily || sap->iSockFamily == KAFUnspec || aFamily == KAFUnspec)
       
   264 					{
       
   265 					rank = EMatchServerUnspecAddr;
       
   266 					sapFound = sap;
       
   267 					continue;
       
   268 					}
       
   269 				}
       
   270 			}
       
   271 
       
   272 		if (rank >= EMatchLocalPort)
       
   273 			continue;
       
   274 
       
   275 		rank = EMatchLocalPort;
       
   276 		sapFound = sap;
       
   277 		}
       
   278 
       
   279 #ifdef _LOG
       
   280 	TBuf<50> src, dst;
       
   281 	//TBuf<50> src2, dst2;
       
   282 	aLocalAddr.OutputWithScope(src);
       
   283 	aRemoteAddr.OutputWithScope(dst);
       
   284 	Log::Printf(_L("\t%S LocateProvider({%S,%d} <--> {%S,%d})"),
       
   285 		&ProtocolName(), &src, port, &dst, aRemoteAddr.Port());
       
   286 	if (sapFound)
       
   287 		{
       
   288 		TBuf<50> src2, dst2;
       
   289 		sapFound->iFlow.FlowContext()->LocalAddr().OutputWithScope(src2);
       
   290 		sapFound->iFlow.FlowContext()->RemoteAddr().OutputWithScope(dst2);
       
   291 		Log::Printf(_L("\t%S SAP[%u] found {%S,%d} <--> {%S,%d}, rank=%d, family=%x"),
       
   292 			&ProtocolName(), (TInt)sapFound,
       
   293 			&src2, port, &dst2, sapFound->iFlow.FlowContext()->RemotePort(),
       
   294 			rank, aFamily);
       
   295 		}
       
   296 	else
       
   297 		{
       
   298 		Log::Printf(_L("\t%S SAP not found, best rank=%d, family=%x"), &ProtocolName(), rank, aFamily);
       
   299 		}
       
   300 #endif
       
   301 
       
   302 	return (CProviderInet6Transport *)sapFound;
       
   303 	}
       
   304 
       
   305 #ifdef _LOG
       
   306 #include "tcp.h"
       
   307 void CProtocolInet6Transport::LogProviders(TUint aPort)
       
   308 	{
       
   309 	CProviderInet6Base *sap;
       
   310 	TBool title = EFalse;
       
   311 
       
   312 	for (sap = CProtocolInet6Base::LocateProvider(aPort); sap != NULL; sap = sap->iNextSAP)
       
   313 		{
       
   314 		if (aPort != sap->iFlow.FlowContext()->LocalPort())
       
   315 			continue;
       
   316 
       
   317 		if (!title)
       
   318 			{
       
   319 			title = ETrue;
       
   320 			Log::Printf(_L("Active TCBs on %S port %d:"), &ProtocolName(), aPort);
       
   321 			}
       
   322 
       
   323 		TBuf<50> src, dst;
       
   324 		sap->iFlow.FlowContext()->LocalAddr().OutputWithScope(src);
       
   325 		sap->iFlow.FlowContext()->RemoteAddr().OutputWithScope(dst);
       
   326 		Log::Printf(_L("\t%S SAP[%u] {%S,%d} <--> {%S,%d} [reuse=%d]   %s"),
       
   327 			&ProtocolName(), (TInt)sap,
       
   328 			&src, sap->iFlow.FlowContext()->LocalPort(),
       
   329 			&dst, sap->iFlow.FlowContext()->RemotePort(),
       
   330 			((CProviderInet6Transport*)sap)->iSockFlags.iReuse,
       
   331 			(sap->iFlow.FlowContext()->Protocol() == KProtocolInetTcp) ?
       
   332 			((CProviderTCP6*)sap)->TcpState() : _S("UDP"));
       
   333 		}
       
   334 	}
       
   335 #endif
       
   336 
       
   337 
       
   338 //
       
   339 // Pick a free port by random from the range [32768,61000].
       
   340 // Random ephemeral port selection will help counter certain
       
   341 // types of attacks.
       
   342 //
       
   343 TUint CProtocolInet6Transport::AssignAutoPort()
       
   344 	{
       
   345 	TUint i, port = KInetMinAutoPort + Random(KInetMaxAutoPort - KInetMinAutoPort + 1);
       
   346 
       
   347 	for (i = KInetMinAutoPort; i <= KInetMaxAutoPort; i++)
       
   348 		{
       
   349 		if (CProtocolInet6Base::LocateProvider(port) == NULL)
       
   350 			return port;
       
   351 		if (++port > KInetMaxAutoPort)
       
   352 			port = KInetMinAutoPort;
       
   353 		}
       
   354 	return KInetPortNone;
       
   355 	}
       
   356 
       
   357 
       
   358 TInt CProtocolInet6Transport::GetIniValue(	const TDesC &aSection,
       
   359 											const TDesC &aName,
       
   360 											TInt aDefault,
       
   361 											TInt aMin,
       
   362 											TInt aMax,
       
   363 											TBool aBoundMode) const
       
   364 /**
       
   365 Reads integer value for ini parameters from tcpip.ini file.
       
   366 
       
   367 @param aSection		Section under which ini parameter belongs ([xxx] tag).
       
   368 @param aName		Name of the ini parameter.
       
   369 @param aDefault		Default value for the parameter, if not given in ini file.
       
   370 @param aMin			Minimum limit for the parameter value.
       
   371 @param aMax			Maximum limit for the parameter value.
       
   372 @param aBoundMode	If ETrue, values that exceed min or max are truncated back to the min/max
       
   373 					boundary. If EFalse, exceeding values are considered invalid, and default
       
   374 					is used for those parameters.
       
   375 
       
   376 @return	Integer value for the parameter.
       
   377 */											
       
   378 	{
       
   379 	LOG(_LIT(KFormat, "\t[%S] %S = %d"));
       
   380 	LOG(_LIT(KFormatInv, "\t[%S] %S = %d is invalid"));
       
   381 
       
   382 	TInt value;
       
   383 	if (!Interfacer()->FindVar(aSection, aName, value))
       
   384 		{
       
   385 		value = aDefault;
       
   386 		}
       
   387 	else
       
   388 		{		
       
   389 		if (value < aMin)
       
   390 			{
       
   391 			LOG(Log::Printf(KFormatInv, &aSection, &aName, value));
       
   392 			value = aBoundMode ? aMin : aDefault;
       
   393 			}
       
   394 		else if (value > aMax)
       
   395 			{
       
   396 			LOG(Log::Printf(KFormatInv, &aSection, &aName, value));
       
   397 			value = aBoundMode ? aMax : aDefault;
       
   398 			}
       
   399 		}
       
   400 	LOG(Log::Printf(KFormat, &aSection, &aName, value));
       
   401 	return value;
       
   402 	}
       
   403 
       
   404 
       
   405 //
       
   406 // Transport Layer Socket Providers
       
   407 //
       
   408 
       
   409 CProviderInet6Transport::CProviderInet6Transport(CProtocolInet6Base *aProtocol)
       
   410 	: CProviderInet6Base(aProtocol)
       
   411 	{
       
   412 	iSockFlags.iRecvClose       = EFalse;
       
   413 	iSockFlags.iSendClose       = EFalse;
       
   414 	iSockFlags.iConnected       = EFalse;
       
   415 	iSockFlags.iFlowStopped     = EFalse;
       
   416 	iSockFlags.iNotify          = ETrue;
       
   417 	iSockFlags.iReuse           = EFalse;
       
   418 	iSockFlags.iAttached        = ETrue;
       
   419 //	iSockFlags.iRawMode         = EFalse;
       
   420 //	iSockFlags.iHeaderIncluded  = EFalse;
       
   421 	iSockFamily                 = KAFUnspec;
       
   422 	iAppFamily                  = KAFUnspec;
       
   423 	}
       
   424 
       
   425 CProviderInet6Transport::~CProviderInet6Transport()
       
   426 	{
       
   427 	}
       
   428 
       
   429 
       
   430 void CProviderInet6Transport::LocalName(TSockAddr &aAddr) const
       
   431 	{
       
   432 	aAddr = iFlow.FlowContext()->LocalAddr();
       
   433 	if (iAppFamily == KAfInet)
       
   434 		TInetAddr::Cast(aAddr).ConvertToV4();
       
   435 	}
       
   436 
       
   437 
       
   438 TInt CProviderInet6Transport::SetLocalName(TSockAddr &aAddr)
       
   439 	{
       
   440 #ifdef _LOG
       
   441 	TBuf<50> a; TInetAddr::Cast(aAddr).OutputWithScope(a);
       
   442 	LOG(Log::Printf(_L("\t%S SAP[%u] SetLocalName({%S,%d}) [reuse=%d]"),
       
   443 		&ProtocolName(), (TInt)this,
       
   444 		&a, aAddr.Port(), iSockFlags.iReuse));
       
   445 #endif
       
   446 
       
   447 	LOG(((CProtocolInet6Transport*)iProtocol)->LogProviders(aAddr.Port()));
       
   448 
       
   449 	TInetAddr addr = aAddr;
       
   450 
       
   451 	// Bound already?
       
   452 	if (iFlow.FlowContext()->LocalPort() != KInetPortNone)
       
   453 		return KErrAlreadyExists;
       
   454 
       
   455 	// Convert an IPv4 address to a V4 Mapped IPv6 address
       
   456 	if (addr.Family() == KAfInet)
       
   457 		addr.ConvertToV4Mapped();
       
   458 
       
   459 	// Check source address
       
   460 	if (addr.Family() != KAFUnspec)
       
   461 		{
       
   462 		iSockFamily = addr.IsV4Mapped() ? KAfInet : KAfInet6;
       
   463 		if (!addr.IsUnspecified())
       
   464 			{
       
   465 			if (addr.Scope() == 0)
       
   466 				{
       
   467 				// Check address and pick a default scope id
       
   468 				addr.SetScope(iProtocol->Interfacer()->LocalScope(addr.Ip6Address(),
       
   469 					iFlow.FlowContext()->LockId(), iFlow.FlowContext()->LockType()));
       
   470 				if (addr.Scope() == 0)
       
   471 					return KErrNotFound;
       
   472 				}
       
   473 			else
       
   474 				{
       
   475 				// Check scoped address
       
   476 				if (addr.Scope() != iProtocol->Interfacer()->LocalScope(addr.Ip6Address(),
       
   477 					addr.Scope(), (TScopeType)(addr.Ip6Address().Scope() - 1)))
       
   478 					return KErrNotFound;
       
   479 				}
       
   480 			}
       
   481 		}
       
   482 
       
   483 	// Autobind requested?
       
   484 	if (addr.Port() == KInetPortNone)
       
   485 		{
       
   486 		addr.SetPort(((CProtocolInet6Transport*)iProtocol)->AssignAutoPort());
       
   487 		if (addr.Port() == KInetPortNone)
       
   488 			return KErrInUse;
       
   489 		}
       
   490 	else
       
   491 		{
       
   492 		if (addr.Port() > 65535)
       
   493 			return KErrTooBig;
       
   494 
       
   495 		if (!iSockFlags.iReuse && Protocol()->LocateSap(EMatchLocalPort, aAddr.Family(), addr))
       
   496 			return KErrInUse;
       
   497 		}
       
   498 
       
   499 	iAppFamily = aAddr.Family();  // aAddr here to get the original family
       
   500 	CProviderInet6Base::SetLocalName(addr);
       
   501 	iSockFlags.iAddressSet = iFlow.FlowContext()->IsLocalSet();
       
   502 	iProtocol->BindProvider(this);
       
   503 	return KErrNone;
       
   504 	}
       
   505 
       
   506 void CProviderInet6Transport::RemName(TSockAddr &aAddr) const
       
   507 	{
       
   508 	aAddr = iFlow.FlowContext()->RemoteAddr();
       
   509 	if (iAppFamily == KAfInet)
       
   510 		TInetAddr::Cast(aAddr).ConvertToV4();
       
   511 	}
       
   512 
       
   513 
       
   514 TInt CProviderInet6Transport::SetRemName(TSockAddr &aAddr)
       
   515 	{
       
   516 	//__ASSERT_DEBUG(!iSockFlags.iConnected && iFlow.FlowContext()->RemoteAddr().IsUnspecified() && iFlow.FlowContext()->RemotePort() == KInetPortNone,
       
   517 	//		 Panic(EInet6Panic_NotSupported));
       
   518 	TInetAddr addr = aAddr; 
       
   519 	
       
   520 #ifdef _LOG
       
   521 	TBuf<50> a; addr.OutputWithScope(a);
       
   522 	LOG(Log::Printf(_L("\t%S SAP[%u] SetRemName({%S,%d})"), &ProtocolName(), (TInt)this, &a, addr.Port());)
       
   523 #endif
       
   524 	TUint port = addr.Port(); 
       
   525 	if (port < 1)
       
   526 		return KErrGeneral;
       
   527 	else if (port > 65535)
       
   528 		return KErrTooBig;
       
   529 
       
   530 	if (addr.IsUnspecified())
       
   531 		return KErrBadName;
       
   532 	
       
   533 	if (addr.Family() == KAfInet)
       
   534 		addr.ConvertToV4Mapped();
       
   535 	
       
   536 	TInt family = addr.IsV4Mapped() ? KAfInet : KAfInet6;
       
   537 
       
   538 	if(iSockFamily == KAFUnspec)
       
   539 		iSockFamily = family;
       
   540 	else if (iSockFamily != family)
       
   541 		return KErrBadName;
       
   542 
       
   543 	iFlow.SetRemoteAddr(addr);
       
   544 	iAppFamily = aAddr.Family();
       
   545 
       
   546 	iSockFlags.iConnected = ETrue;
       
   547 	return KErrNone;
       
   548 	}
       
   549 
       
   550 
       
   551 void CProviderInet6Transport::AutoBind()
       
   552 	{
       
   553 	//__ASSERT_DEBUG(iFlow.FlowContext()->LocalPort()==KInetPortNone, Panic(EInet6Panic_BadBind));
       
   554 	TInetAddr localAddr;
       
   555 
       
   556 	// Socket is already bound?
       
   557 	if (iFlow.FlowContext()->LocalPort()!=KInetPortNone)
       
   558 		return;
       
   559 
       
   560 	localAddr.SetPort(((CProtocolInet6Transport *)iProtocol)->AssignAutoPort());
       
   561 	if (localAddr.Port()==KInetPortNone)
       
   562 		{
       
   563 		Error(KErrInUse);
       
   564 		return;
       
   565 		}
       
   566 
       
   567 	iFlow.SetLocalAddr(localAddr);
       
   568 
       
   569 #ifdef _LOG
       
   570 	TBuf<50> addr; iFlow.FlowContext()->LocalAddr().OutputWithScope(addr);
       
   571 	Log::Printf(_L("\t%S SAP[%u] AutoBind() --> {%S,%d}"), &ProtocolName(), (TInt)this, &addr, iFlow.FlowContext()->LocalPort());
       
   572 #endif
       
   573 
       
   574 	iProtocol->BindProvider(this);
       
   575 	}
       
   576 
       
   577 TInt CProviderInet6Transport::SetOption(TUint aLevel, TUint aName, const TDesC8& aOption)
       
   578 	{
       
   579 	TInt ret = KErrNotSupported;
       
   580 
       
   581 	if (aLevel == KSolInetIp && aName == KSoReuseAddr)
       
   582 		{
       
   583 		TInt intValue;
       
   584 		ret = GetOptionInt(aOption, intValue);
       
   585 		if (ret == KErrNone)
       
   586 			iSockFlags.iReuse = intValue ? TRUE : FALSE;
       
   587 		#ifdef _LOG 
       
   588       	  Log::Printf(_L("SetOpt\t%S SAP[%u] KSoReuseAddr = %d err=%d"), 
       
   589       		           &ProtocolName(), (TInt)this, (TInt)iSockFlags.iReuse, ret); 
       
   590         #endif 
       
   591 		}
       
   592 
       
   593 	if (ret == KErrNotSupported)
       
   594 		ret = CProviderInet6Base::SetOption(aLevel, aName, aOption);
       
   595 	
       
   596 #ifdef SYMBIAN_NETWORKING_UPS	
       
   597 	if (ret == KErrNone && aLevel == KSOLProvider && aName == (TUint) KSoConnectionInfo)
       
   598 		{
       
   599 		iConnectionInfoReceived = 1;
       
   600 		}
       
   601 #endif	
       
   602 	
       
   603 	return ret;
       
   604 	}
       
   605 
       
   606 
       
   607 TInt CProviderInet6Transport::GetOption(TUint aLevel, TUint aName, TDes8& aOption) const
       
   608 	{
       
   609 	TInt ret = KErrNotSupported;
       
   610 
       
   611 	if (aLevel == KSolInetIp && aName == KSoReuseAddr)
       
   612 		ret = SetOptionInt(aOption, iSockFlags.iReuse);
       
   613 
       
   614 	if (ret == KErrNotSupported)
       
   615 		ret = CProviderInet6Base::GetOption(aLevel, aName, aOption);
       
   616 
       
   617 	return ret;
       
   618 	}
       
   619 
       
   620 void CProviderInet6Transport::CanSend()
       
   621 	{
       
   622 	LOG(Log::Printf(_L("\t%S SAP[%u] CanSend()"), &ProtocolName(), (TInt)this));
       
   623 	// Do not enable data flow if the protocol doesn't want it.
       
   624 	if(!iSockFlags.iFlowStopped && iSockFlags.iNotify)
       
   625 		CProviderInet6Base::CanSend();
       
   626 	}
       
   627 
       
   628 void CProviderInet6Transport::Error(TInt aError, TUint aOperationMask)
       
   629 	{
       
   630 	if (iSockFlags.iNotify)
       
   631 		CProviderInet6Base::Error(aError, aOperationMask);
       
   632 	if (FatalState())
       
   633 		iSockFlags.iNotify = EFalse;
       
   634 	}
       
   635 
       
   636 void CProviderInet6Transport::IcmpError(TInt aError, TUint aOperationMask, TInt aType, TInt aCode,
       
   637 		const TInetAddr& aSrcAddr, const TInetAddr& aDstAddr, const TInetAddr& aErrAddr)
       
   638 	{
       
   639 	CProviderInet6Base::SaveIcmpError(aType, aCode, aSrcAddr, aDstAddr, aErrAddr);
       
   640 	if (iAppFamily == KAfInet)
       
   641 		{
       
   642 		iLastError.iSrcAddr.ConvertToV4();
       
   643 		iLastError.iDstAddr.ConvertToV4();
       
   644 		iLastError.iErrAddr.ConvertToV4();
       
   645 		}
       
   646 
       
   647 	if (iSockFlags.iReportIcmp && aError != KErrNone)
       
   648 		Error(aError, aOperationMask);
       
   649 	}
       
   650 
       
   651 #ifdef SYMBIAN_NETWORKING_UPS
       
   652 TBool CProviderInet6Transport::ConnectionInfoSet()
       
   653 	{
       
   654 	return static_cast<TBool>(iConnectionInfoReceived);
       
   655 	}
       
   656 
       
   657 
       
   658 TBool CProviderInet6Transport::HasSocket()	
       
   659 	{
       
   660 	if (iSocket == NULL)
       
   661 		{
       
   662 	   	return EFalse;
       
   663 	    }
       
   664 	else
       
   665 		{
       
   666 		return ETrue;	
       
   667 		}	
       
   668 	}
       
   669 
       
   670 void *CProviderInet6Transport::GetApiL(const TDesC8& aApiName, TUint* aVersion)
       
   671 	{
       
   672 	if (aApiName == _L8("MProviderBindings"))
       
   673 		{
       
   674 	    return EXPORT_API_L(MProviderBindings, static_cast<MProviderBindings*>(this), aVersion);
       
   675 		}
       
   676 
       
   677 	return NULL;	
       
   678 	}
       
   679 #endif
       
   680 
       
   681 void RMBufSockQ::AppendL(const TDesC8& aData, TInt aLen)
       
   682 	{
       
   683 	if (aLen <= 0)
       
   684 		return;
       
   685 
       
   686 	RMBufChain seg;
       
   687 	seg.AllocL(aLen);
       
   688 	seg.CopyIn(aData);
       
   689 	RMBufChain::Append(seg);
       
   690 	}
       
   691 
       
   692 TInt RMBufSockQ::AppendDes(const TDesC8& aData, TInt aLen)
       
   693 	{
       
   694 	if (aLen <= 0)
       
   695 		return KErrNone;
       
   696 
       
   697 	RMBufChain seg;
       
   698 	TInt err = seg.Alloc(aLen);
       
   699 	if(err == KErrNone)
       
   700 		{
       
   701 		seg.CopyIn(aData);
       
   702 		RMBufChain::Append(seg);
       
   703 		}
       
   704 	return err;
       
   705 	}
       
   706 
       
   707 
       
   708 //
       
   709 // Append at least aLength bytes from aChain.
       
   710 // Leave the remainder in aChain. Return number
       
   711 // of bytes removed from aChain.
       
   712 //
       
   713 TInt RMBufSockQ::AppendAtLeast(RMBufChain& aChain, TInt aLength)
       
   714 	{
       
   715 	TInt o, n;
       
   716 	RMBuf* m, *p;
       
   717 
       
   718 	if (!aChain.Goto(aLength, m, o, n, p))
       
   719 		{
       
   720 		aLength = aChain.Length();
       
   721 		RMBufChain::Append(aChain);
       
   722 		return aLength;
       
   723 		}
       
   724 
       
   725 	if (o != m->Offset())
       
   726 		{
       
   727 		p = m;
       
   728 		m = m->Next();
       
   729 		aLength += n;
       
   730 		}
       
   731 
       
   732 	p->Unlink();
       
   733 	RMBufChain::Append(aChain);
       
   734 	aChain = m;
       
   735 
       
   736 	return aLength;
       
   737 	}
       
   738 
       
   739 //
       
   740 // Remove at most aLength bytes from the queue.
       
   741 // Place the result in aChain. Return number
       
   742 // of bytes removed from the queue.
       
   743 //
       
   744 TInt RMBufSockQ::RemoveAtMost(RMBufChain& aChain, TInt aLength)
       
   745 	{
       
   746 	TInt o, n;
       
   747 	RMBuf* m, *p;
       
   748 
       
   749 	if (aLength <= 0 || iNext == NULL)
       
   750 		return 0;
       
   751 
       
   752 	if (!Goto(aLength, m, o, n, p))
       
   753 		{
       
   754 		aChain = iNext;
       
   755 		iNext = NULL;
       
   756 		return aChain.Length();
       
   757 		}
       
   758 
       
   759 	p->Unlink();
       
   760 	aChain = iNext;
       
   761 	iNext = m;
       
   762 
       
   763 	return aLength + m->Offset() - o;
       
   764 	}
       
   765 
       
   766 //
       
   767 // Copy aLength bytes from aQueue at aOffset
       
   768 //
       
   769 void TDualBufPtr::CopyInL(const RMBufChain& aQueue, TInt aOffset, TInt aLength)
       
   770 	{
       
   771 	switch(iType)
       
   772 		{
       
   773 	case ERMBufChain:
       
   774 		if (aLength > 0)
       
   775 			aQueue.CopyL(*iChain, aOffset, aLength);
       
   776 		break;
       
   777 
       
   778 	case EDes8:
       
   779 		iDesc->SetLength(aLength);
       
   780 		if (aLength > 0)
       
   781 			aQueue.CopyOut(*iDesc, aOffset);
       
   782 		break;
       
   783 
       
   784 	default:
       
   785 		Panic(EInet6Panic_NotSupported);
       
   786 		}
       
   787 	}
       
   788 
       
   789 //
       
   790 // Copy aLength bytes from aQueue at aOffset
       
   791 //
       
   792 TInt TDualBufPtr::CopyIn(const RMBufChain& aQueue, TInt aOffset, TInt aLength)
       
   793 	{
       
   794 	switch(iType)
       
   795 		{
       
   796 	case ERMBufChain:
       
   797 		if (aLength > 0)
       
   798 			return aQueue.Copy(*iChain, aOffset, aLength);
       
   799 		break;
       
   800 
       
   801 	case EDes8:
       
   802 		iDesc->SetLength(aLength);
       
   803 		if (aLength > 0)
       
   804 			aQueue.CopyOut(*iDesc, aOffset);
       
   805 		break;
       
   806 
       
   807 	default:
       
   808 		Panic(EInet6Panic_NotSupported);
       
   809 		}
       
   810 	return KErrNone;
       
   811 	}
       
   812 
       
   813 //
       
   814 // Copy into aChain at aOffset
       
   815 //
       
   816 void TDualBufPtr::CopyOut(RMBufChain& aChain, TInt aOffset) const
       
   817 	{
       
   818 	switch(iType)
       
   819 		{
       
   820 	case EDes8:
       
   821 	case EDesC8:
       
   822 		aChain.CopyIn(*iDesc, aOffset);
       
   823 		break;
       
   824 
       
   825 	default:
       
   826 		Panic(EInet6Panic_NotSupported);
       
   827 		}
       
   828 	}
       
   829 
       
   830 //
       
   831 // Remove aLength bytes from the beginning of aQueue.
       
   832 //
       
   833 TInt TDualBufPtr::Consume(RMBufChain& aQueue, TInt aLength, RMBufAllocator& aAllocator)
       
   834 	{
       
   835 	RMBufChain tail;
       
   836 	TInt err;
       
   837 
       
   838 	switch(iType)
       
   839 		{
       
   840 	case ERMBufChain:
       
   841 		if (aLength > 0)
       
   842 			{
       
   843 			err = aQueue.Split(aLength, tail, aAllocator);
       
   844 			if (err == KErrNone)
       
   845 				{
       
   846 				iChain->Assign(aQueue);
       
   847 				aQueue.Assign(tail);
       
   848 				}
       
   849 			else
       
   850 				{
       
   851 				aLength = RMBufSockQ::Cast(aQueue).RemoveAtMost(*iChain, aLength);
       
   852 				LOG(Log::Printf(_L("TDualBufPtr::Consume(): Alloc problem. Returning less")));
       
   853 				}
       
   854 			}
       
   855 		break;
       
   856 
       
   857 	case EDes8:
       
   858 		iDesc->SetLength(aLength);
       
   859 		if (aLength > 0)
       
   860 			{
       
   861 			aQueue.CopyOut(*iDesc);
       
   862 			aQueue.TrimStart(aLength);
       
   863 			}
       
   864 		break;
       
   865 
       
   866 	default:
       
   867 		Panic(EInet6Panic_NoData);
       
   868 		}
       
   869 	return aLength;
       
   870 	}
       
   871 
       
   872 //
       
   873 // Append at least aLength bytes to aQueue
       
   874 //
       
   875 TInt TDualBufPtr::AppendL(RMBufChain& aQueue, TInt aLength)
       
   876 	{
       
   877 	switch(iType)
       
   878 		{
       
   879 	case ERMBufChain:
       
   880 		aLength = RMBufSockQ::Cast(aQueue).AppendAtLeast(*iChain, aLength);
       
   881 		break;
       
   882 
       
   883 	case EDes8:
       
   884 	case EDesC8:
       
   885 		RMBufSockQ::Cast(aQueue).AppendL(*iDesc, aLength);
       
   886 		break;
       
   887 
       
   888 	default:
       
   889 		Panic(EInet6Panic_NoData);
       
   890 		}
       
   891 
       
   892 	return aLength;
       
   893 	}
       
   894 
       
   895 //
       
   896 // Append at least aLength bytes to aQueue. Panics if used with des-tyoe
       
   897 //
       
   898 TInt TDualBufPtr::Append(RMBufChain& aQueue, TInt aLength)
       
   899 	{
       
   900 	switch(iType)
       
   901 		{
       
   902 	case ERMBufChain:
       
   903 		aLength = RMBufSockQ::Cast(aQueue).AppendAtLeast(*iChain, aLength);
       
   904 		break;
       
   905 
       
   906 	default:
       
   907 		Panic(EInet6Panic_NoData);
       
   908 		}
       
   909 
       
   910 	return aLength;
       
   911 	}
       
   912 
       
   913 //
       
   914 // Free buffer
       
   915 //
       
   916 void TDualBufPtr::Free()
       
   917 	{
       
   918 	switch(iType)
       
   919 		{
       
   920 	case ERMBufChain:
       
   921 		iChain->Free();
       
   922 		break;
       
   923 
       
   924 	case EDes8:
       
   925 		iDesc->SetLength(0);
       
   926 		break;
       
   927 
       
   928 	default:
       
   929 		Panic(EInet6Panic_NoData);
       
   930 		}
       
   931 	}
       
   932 
       
   933 #ifdef __ARMCC__
       
   934 #pragma pop
       
   935 #endif