networkprotocols/tcpipv4v6prt/src/inet.cpp
changeset 0 af10295192d8
child 53 7e41d162e158
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 // inet.cpp - inet protocol base
       
    15 //
       
    16 
       
    17 #include <in_pkt.h>
       
    18 #include <ext_hdr.h>
       
    19 #include <comms-infras/nifif.h>
       
    20 #include <comms-infras/nifif_internal.h>
       
    21 #include "inet.h"
       
    22 #include "networkinfo.h"
       
    23 #include "inet6log.h"
       
    24 
       
    25 //
       
    26 //  CProtocolInet6Base
       
    27 //
       
    28 //
       
    29 
       
    30 CProtocolInet6Base::CProtocolInet6Base()
       
    31 	{
       
    32 	// Nothing here -- rely on CBase zero fill!
       
    33 	}
       
    34 
       
    35 void CProtocolInet6Base::InitL(TDesC& /*aTag*/)
       
    36 	{
       
    37 #ifdef _LOG
       
    38 	// Fetch the protocol name for logging purposes
       
    39 	TServerProtocolDesc info;
       
    40 	Identify(&info);
       
    41 	iName = info.iName;
       
    42 #endif
       
    43 	}
       
    44 
       
    45 void CProtocolInet6Base::BindL(CProtocolBase* /*aProtocol*/, TUint /*aId*/)
       
    46 	{
       
    47 	Panic(EInet6Panic_NotSupported);
       
    48 	}
       
    49 
       
    50 void CProtocolInet6Base::Unbind(CProtocolBase* /*aProtocol*/, TUint /*aId*/)
       
    51 	{
       
    52 	}
       
    53 
       
    54 void CProtocolInet6Base::StartL()
       
    55 	{
       
    56 	}
       
    57 
       
    58 //
       
    59 //	*NOTE*
       
    60 //		In the INET6 stack the Error upcall is passed up from the drivers
       
    61 //		but, it does not require any actions by default (doing something
       
    62 //		here is only useful for protocols modules that want to know about
       
    63 //		changes in the interfaces and possibly doing there own
       
    64 //		reconfiguring after this (for example, 6to4).
       
    65 //
       
    66 //		In INET6 the interface manager takes care of notifying individual
       
    67 //		flows about the interface changes that affect them. -- msa
       
    68 //
       
    69 //	This here is required, because the base CProtocolBase::Error()
       
    70 //	calls Panic. A similar consideration applies to the StartSending(),
       
    71 //	but as the CProtocolBase::StartSending() is already a NOP, nothing
       
    72 //	needs to be done here.
       
    73 //
       
    74 void CProtocolInet6Base::Error(TInt /*anError*/, CProtocolBase* /*aSourceProtocol*/)
       
    75 	{
       
    76 	}
       
    77 
       
    78 
       
    79 CProtocolInet6Base::~CProtocolInet6Base()
       
    80 	{
       
    81 	// All SAP's should have been detached from this by now!
       
    82 	ASSERT(iSapCount == 0);
       
    83 	}
       
    84 
       
    85 
       
    86 //
       
    87 // SAP counting
       
    88 //
       
    89 void CProtocolInet6Base::IncSAPs()
       
    90 	{
       
    91 	iSapCount++;
       
    92 	}
       
    93 
       
    94 void CProtocolInet6Base::DecSAPs()
       
    95 	{
       
    96 	ASSERT(iSapCount > 0);
       
    97 	iSapCount--;
       
    98 	}
       
    99 
       
   100 //
       
   101 // SAP database routines
       
   102 //
       
   103 void CProtocolInet6Base::BindProvider(CProviderInet6Base* aSAP)
       
   104 	{
       
   105 #ifdef _LOG
       
   106 	TBuf<50> local; aSAP->iFlow.FlowContext()->LocalAddr().OutputWithScope(local);
       
   107 	TBuf<50> remote; aSAP->iFlow.FlowContext()->RemoteAddr().OutputWithScope(remote);
       
   108 	Log::Printf(_L("\t%S SAP[%u] BindProvider({%S,%d} <--> {%S,%d})"),
       
   109 				&ProtocolName(), (TInt)aSAP,
       
   110 				&local, aSAP->iFlow.FlowContext()->LocalPort(), &remote, aSAP->iFlow.FlowContext()->RemotePort());
       
   111 #endif
       
   112 
       
   113 	TUint key = ProviderHashKey(aSAP->iFlow.FlowContext()->LocalPort());
       
   114 	aSAP->iNextSAP = iSAP[key];
       
   115 	iSAP[key] = aSAP;
       
   116 	}
       
   117 
       
   118 void CProtocolInet6Base::QueueBindProvider(CProviderInet6Base* aSAP)
       
   119 	{
       
   120 #ifdef _LOG
       
   121 	TBuf<50> local; aSAP->iFlow.FlowContext()->LocalAddr().OutputWithScope(local);
       
   122 	TBuf<50> remote; aSAP->iFlow.FlowContext()->RemoteAddr().OutputWithScope(remote);
       
   123 	Log::Printf(_L("\t%S SAP[%u] QueueBindProvider(): {%S,%d} <--> {%S,%d}"),
       
   124 			&ProtocolName(), (TInt)this,
       
   125 			&local, aSAP->iFlow.FlowContext()->LocalPort(), &remote, aSAP->iFlow.FlowContext()->RemotePort());
       
   126 #endif
       
   127 
       
   128 	TUint key = ProviderHashKey(aSAP->iFlow.FlowContext()->LocalPort());
       
   129 	CProviderInet6Base **sap = &iSAP[key];
       
   130 	while (*sap != NULL)
       
   131 		sap = &(*sap)->iNextSAP;
       
   132 	*sap = aSAP;
       
   133 	}
       
   134 
       
   135 void CProtocolInet6Base::UnbindProvider(CProviderInet6Base* aSAP)
       
   136 	{
       
   137 	CProviderInet6Base **sapPtr;
       
   138 	TUint key;
       
   139 
       
   140 	if (aSAP->iFlow.FlowContext() == NULL)
       
   141 		return;
       
   142 
       
   143 	key = ProviderHashKey(aSAP->iFlow.FlowContext()->LocalPort());
       
   144 	for (sapPtr = &iSAP[key]; *sapPtr != NULL; sapPtr = &((*sapPtr)->iNextSAP))
       
   145 		if (*sapPtr == aSAP)
       
   146 			{
       
   147 #ifdef _LOG
       
   148 			TBuf<50> local; aSAP->iFlow.FlowContext()->LocalAddr().OutputWithScope(local);
       
   149 			TBuf<50> remote; aSAP->iFlow.FlowContext()->RemoteAddr().OutputWithScope(remote);
       
   150 			Log::Printf(_L("\t%S SAP[%u] UnbindProvider({%S,%d} <--> {%S,%d})"),
       
   151 					&ProtocolName(), (TInt)aSAP,
       
   152 					&local, aSAP->iFlow.FlowContext()->LocalPort(), &remote, aSAP->iFlow.FlowContext()->RemotePort());
       
   153 #endif
       
   154 			*sapPtr = (*sapPtr)->iNextSAP;
       
   155 			aSAP->iNextSAP = NULL;
       
   156 			return;
       
   157 			}
       
   158 	}
       
   159 
       
   160 CProviderInet6Base* CProtocolInet6Base::LocateProvider(TUint aPort)
       
   161 	{
       
   162 	CProviderInet6Base *sap;
       
   163 	TUint key = ProviderHashKey(aPort);
       
   164 
       
   165 	for (sap = iSAP[key]; sap != NULL; sap = sap->iNextSAP)
       
   166 		if (sap->iFlow.FlowContext()->LocalPort() == aPort)
       
   167 			return sap;
       
   168 
       
   169 	return NULL;
       
   170 	}
       
   171 
       
   172 void CProviderInet6Base::InitL()
       
   173 	{
       
   174 	TInt err = iFlow.Open(iProtocol->NetworkService());
       
   175 	if (err != KErrNone)
       
   176  		User::Leave(err);
       
   177 
       
   178 	iFlow.SetNotify(this);
       
   179 
       
   180 	iLastError.iStatus  = KErrNone;
       
   181 	iLastError.iErrType = 0;
       
   182 	iLastError.iErrCode = 0;
       
   183 	iErrorMask          = 0;
       
   184 	}
       
   185 
       
   186 void CProviderInet6Base::Start()
       
   187 	{
       
   188 #if 0
       
   189   // XXX - Setting socket write buffer to 1024 seems to seriously
       
   190   // hamper TCP performance over loopback. Default is 4096 and 2048
       
   191   // also works ok. Have to look at this later. -ML
       
   192   TVersion v = RNif::Version();
       
   193   TUint32 ver = (v.iMajor << 24) | (v.iMinor << 16) | v.iBuild;
       
   194   if (ver >= 0x01000044)
       
   195 	Nif::SetSocketState(ENifBuffers1024, this);
       
   196 #endif
       
   197 	}
       
   198 
       
   199 
       
   200 //
       
   201 //  CProviderInet6Base
       
   202 //
       
   203 //
       
   204 
       
   205 CProviderInet6Base::CProviderInet6Base(CProtocolInet6Base* aProtocol) : iProtocol(aProtocol)
       
   206 	{
       
   207 	LOG(Log::Printf(_L("\t%S SAP[%u] New"), &ProtocolName(), (TInt)this));
       
   208 	iNextSAP = NULL;
       
   209 	iProtocol->Open();
       
   210 	iProtocol->IncSAPs();
       
   211 	if (iIsUser == 0)
       
   212 		{
       
   213 		iProtocol->NetworkService()->IncUsers();
       
   214 		iIsUser = 1;
       
   215 		}
       
   216 	}
       
   217 
       
   218 CProviderInet6Base::~CProviderInet6Base()
       
   219 	{
       
   220 	((CProtocolInet6Base*)iProtocol)->UnbindProvider(this);
       
   221 	CFlowContext *flow = iFlow.FlowContext();
       
   222 	if (flow) 
       
   223 		{
       
   224 		TPckgBuf< TInt > opt(0);  // Currently there is no use for the option parameter
       
   225 		flow->SetOption(KSOLProvider, KSoFlowClosing, opt);
       
   226 		}
       
   227 	iFlow.Close();
       
   228 	if (iIsUser == 1)
       
   229 		{
       
   230 		iProtocol->NetworkService()->DecUsers();
       
   231 		iIsUser = 0;
       
   232 		}
       
   233 	iProtocol->DecSAPs();
       
   234 	LOG(Log::Printf(_L("\t%S SAP[%u] Deleted"), &ProtocolName(), (TInt)this));
       
   235 	iProtocol->Close();
       
   236 	}
       
   237 
       
   238 
       
   239 void CProviderInet6Base::ActiveOpen()
       
   240 	{
       
   241 	Panic(EInet6Panic_NotSupported);
       
   242 	}
       
   243 
       
   244 
       
   245 TInt CProviderInet6Base::PassiveOpen(TUint /*aQueSize*/)
       
   246 	{
       
   247 	Panic(EInet6Panic_NotSupported);
       
   248 	return 0;
       
   249 	}
       
   250 
       
   251 
       
   252 void CProviderInet6Base::ActiveOpen(const TDesC8& /*aConnectionData*/)
       
   253 	{
       
   254 	Panic(EInet6Panic_NotSupported);
       
   255 	}
       
   256 
       
   257 
       
   258 TInt CProviderInet6Base::PassiveOpen(TUint /*aQueSize*/,const TDesC8& /*aConnectionData*/)
       
   259 	{
       
   260 	Panic(EInet6Panic_NotSupported);
       
   261 	return 0;
       
   262 	}
       
   263 
       
   264 void CProviderInet6Base::Shutdown(TCloseType /*option*/,const TDesC8& /*aDisconnectionData*/)
       
   265 	{
       
   266 	Panic(EInet6Panic_NotSupported);
       
   267 	}
       
   268 
       
   269 // *NOTE*
       
   270 //	Why are level KSoInetIfCtrl and KSoInetRtCtrl handled at this
       
   271 //	level? Why not just let iProtocol->SetOption() handle them (as
       
   272 //	would be logical)? The reason is KSoInetEnum*/KSoInetNext*, which
       
   273 //	need a SAP specific context, and that is *NOT* provided by the
       
   274 //	iProtocol->SetOption interface. However, only these options are
       
   275 //	handled here, rest of the KSoInetRtCtrl/KSoInetIfCtrl are passed
       
   276 //	to the protocol -- msa
       
   277 //
       
   278 TInt CProviderInet6Base::SetOption(TUint aLevel, TUint aName, const TDesC8& aOption)
       
   279 	{
       
   280 	if (aLevel == KSolInetIp)
       
   281 		{
       
   282 		// Prefetch the option parameter (error return is ignored,
       
   283 		// if the option is not implemented at this level).
       
   284 		TInt val;
       
   285 		const TInt ret = GetOptionInt(aOption, val);
       
   286 
       
   287 		switch (aName)
       
   288 			{
       
   289 		case KSoHeaderIncluded:
       
   290 		case KSoRawMode:
       
   291 			// *note* Need to arrange KErrNotSupported for TCP! -- msa
       
   292 
       
   293 			// Implementation of setting HeaderIncluded and RawMode options
       
   294 			if (ret != KErrNone)
       
   295 				return ret;
       
   296 			// [The raw/headerincluded logic here is unnecessarily convoluted.
       
   297 			// In EPOC they could be handled independently, as there is no
       
   298 			// special priviledges required for setting the raw mode either.
       
   299 			// But, because it is specified to work in this way, sigh ...
       
   300 			// -- msa]
       
   301 			//
       
   302 			// Only allow setting of iHeaderIncluded when iRawMode is set
       
   303 			// Clearing is always allowed.
       
   304 			// When iRawMode==0, then *ALWAYS* iHeaderIncluded == 0
       
   305 			if (aName == KSoRawMode)
       
   306 				{
       
   307 				if (val)
       
   308 					iRawMode = 1;
       
   309 				else
       
   310 					{
       
   311 					iRawMode = 0;
       
   312 					iHeaderIncluded = 0;
       
   313 					}
       
   314 				}
       
   315 			else if (val == 0)
       
   316 				iHeaderIncluded = 0;
       
   317 			else if (iRawMode)
       
   318 				{
       
   319 				iHeaderIncluded = 1;
       
   320 				}
       
   321 			else
       
   322 				return KErrNotSupported; // attempted to set KSoHeaderIncluded without Raw mode
       
   323 #ifdef _LOG
       
   324 			Log::Printf(_L("SetOpt\t%S SAP[%u] RawMode=%d HeaderInclude=%d"),
       
   325 				&ProtocolName(), (TInt)this, iRawMode, iHeaderIncluded);
       
   326 #endif
       
   327 			return KErrNone;
       
   328 
       
   329 		case KSoUserSocket:
       
   330 			if (ret != KErrNone)
       
   331 				return ret;
       
   332 #ifdef _LOG
       
   333 			Log::Printf(_L("SetOpt\t%S SAP[%u] KSoUserSocket %d -> %d"),
       
   334 				&ProtocolName(), (TInt)this, iIsUser, val);
       
   335 #endif
       
   336 			if ((TUint)val == iIsUser)
       
   337 				return KErrNone;	// No change in state
       
   338 			else if (val == 0)
       
   339 				{
       
   340 				iProtocol->NetworkService()->DecUsers();
       
   341 				iIsUser = 0;
       
   342 				return KErrNone;
       
   343 				}
       
   344 			else if (val == 1)
       
   345 				{
       
   346 				iProtocol->NetworkService()->IncUsers();
       
   347 				iIsUser = 1;
       
   348 				return KErrNone;
       
   349 				}
       
   350 			else
       
   351 				return KErrArgument;
       
   352 		default:
       
   353 			// For now, give generic LOG here, but should really log at each implementation -- msa
       
   354 			LOG(Log::Printf(_L("SetOpt\t%S SAP[%u] level=KSolInetIp name=%d"), &ProtocolName(), (TInt)this, aName));
       
   355 			break;
       
   356 			}
       
   357 		}
       
   358 	else if (aLevel == KSolInetIfCtrl)
       
   359 		{
       
   360 		if (aName == STATIC_CAST(TUint, KSoInetEnumInterfaces))	// See *NOTE* above!
       
   361 			{
       
   362 			iInterfaceIndex = 0;
       
   363 			LOG(Log::Printf(_L("SetOpt\t%S SAP[%u] KSoInetEnumInterfaces"), &ProtocolName(), (TInt)this));
       
   364 			return KErrNone;
       
   365 			}
       
   366 		}
       
   367 	else if (aLevel == KSolInetRtCtrl)
       
   368 		{
       
   369 		if (aName == STATIC_CAST(TUint, KSoInetEnumRoutes))	// See *NOTE* above!
       
   370 			{
       
   371 			iRouteIndex = 0;
       
   372 			LOG(Log::Printf(_L("SetOpt\t%S SAP[%u] KSoInetEnumRoutes"), &ProtocolName(), (TInt)this));
       
   373 			return KErrNone;
       
   374 			}
       
   375 		}
       
   376 	else if (aLevel == KNifOptLevel)
       
   377 		{
       
   378 		return KErrNotSupported;
       
   379 		}
       
   380 	if (iFlow.FlowContext())
       
   381 		{
       
   382 		const TInt ret = iFlow.FlowContext()->SetOption(aLevel, aName, aOption);
       
   383 		if (ret != KErrNotSupported)
       
   384 			return ret;
       
   385 		}
       
   386 	return iProtocol->Interfacer()->SetOption(aLevel, aName, aOption, *this);
       
   387 	}
       
   388 
       
   389 TInt CProviderInet6Base::GetOption(TUint aLevel, TUint aName, TDes8& aOption) const
       
   390 	{
       
   391 	LOG(Log::Printf(_L("GetOpt\t%S SAP[%u] level=%x, name=%x, len=%d"), &iProtocol->ProtocolName(), (TInt)this, aLevel, aName, aOption.Length());)
       
   392 	if (aLevel == KSolInetIp)
       
   393 		switch (aName)
       
   394 		{
       
   395 		case KSoInetLastError:
       
   396 			if (STATIC_CAST(TUint, aOption.MaxLength()) >= sizeof(iLastError))
       
   397 				{
       
   398 				aOption.SetLength(sizeof(TSoInetLastErr));
       
   399 				aOption.Copy((TUint8*)&iLastError, sizeof(iLastError));
       
   400 				return KErrNone;
       
   401 				}
       
   402 			return KErrTooBig;
       
   403 			
       
   404 		case KSoHeaderIncluded:
       
   405 			return SetOptionInt(aOption, iHeaderIncluded);
       
   406 		case KSoRawMode:
       
   407 			return SetOptionInt(aOption, iRawMode);
       
   408 		case KSoUserSocket:
       
   409 			return SetOptionInt(aOption, iIsUser != 0);
       
   410 
       
   411 		default:
       
   412 			break;
       
   413 		}
       
   414 	else if (aLevel == KSolInetIfCtrl && aName == STATIC_CAST(TUint, KSoInetNextInterface))	// See *NOTE* above!
       
   415 		{
       
   416 		TSoInetInterfaceInfo& opt = *(TSoInetInterfaceInfo*)aOption.Ptr();
       
   417 		if (STATIC_CAST(TUint, aOption.MaxLength()) < sizeof(TSoInetInterfaceInfo))
       
   418 			return KErrTooBig;
       
   419 		(void) new (&opt) TSoInetInterfaceInfo;	// Make sure descriptors are correct.
       
   420 		aOption.SetLength(sizeof(TSoInetInterfaceInfo));
       
   421 		((CProviderInet6Base *)this)->iInterfaceIndex = iProtocol->Interfacer()->InterfaceInfo(iInterfaceIndex, opt);
       
   422 		if (iInterfaceIndex > 0)
       
   423 			return KErrNone;
       
   424 		else
       
   425 			return KErrNotFound;
       
   426 		}
       
   427 	else if (aLevel == KSolInetRtCtrl && aName == STATIC_CAST(TUint, KSoInetNextRoute))	// See *NOTE* above!
       
   428 		{
       
   429 		TSoInetRouteInfo& opt = *(TSoInetRouteInfo*)aOption.Ptr();
       
   430 		if (STATIC_CAST(TUint, aOption.MaxLength()) < sizeof(TSoInetRouteInfo))
       
   431 			return KErrTooBig;
       
   432 		aOption.SetLength(sizeof(TSoInetRouteInfo));
       
   433 		(void) new (&opt) TSoInetRouteInfo; // Make sure descriptors are correct.
       
   434 		((CProviderInet6Base *)this)->iRouteIndex = iProtocol->Interfacer()->RouteInfo(iRouteIndex, opt);
       
   435 		if (iRouteIndex > 0)
       
   436 			return KErrNone;
       
   437 		else
       
   438 			return KErrNotFound;
       
   439 		}
       
   440 	else if (aLevel == KNifOptLevel)
       
   441 		{
       
   442 		return KErrNotSupported;
       
   443 		}
       
   444 	//
       
   445 	// if none of the above "supported", falls here...
       
   446 	//
       
   447 	CFlowContext *flow = iFlow.FlowContext();
       
   448 	if (flow)
       
   449 		{
       
   450 		const TInt ret = flow->GetOption(aLevel, aName, aOption);
       
   451 		if (ret != KErrNotSupported)
       
   452 			return ret;
       
   453 		}
       
   454 	return iProtocol->Interfacer()->GetOption(aLevel, aName, aOption, *((CProviderInet6Base *)this));
       
   455 	}
       
   456 
       
   457 void CProviderInet6Base::Ioctl(TUint aLevel, TUint aName, TDes8* /*anOption*/)
       
   458 	{
       
   459 	LOG(Log::Printf(_L("Ioctl\t%S SAP[%u] %x, %x)"), &ProtocolName(), (TInt)this, aLevel, aName));
       
   460 	if (aLevel == KSolInetIp && aName == KIoctlInetLastError)
       
   461 		{
       
   462 		TPckg<TSoInetLastErr> lastError(iLastError);
       
   463 		iSocket->IoctlComplete(&lastError);
       
   464 		}
       
   465 	else
       
   466 		Error(KErrNotSupported, MSocketNotify::EErrorIoctl);
       
   467 	}
       
   468 
       
   469 void CProviderInet6Base::CancelIoctl(TUint aLevel, TUint aName)
       
   470 	{
       
   471 #ifdef _LOG
       
   472 	Log::Printf(_L("CancelIoctl\t%S SAP[%u] %x, %x)"), &ProtocolName(), (TInt)this, aLevel, aName);
       
   473 #else
       
   474 	(void)aLevel;	// silence compiler warning
       
   475 	(void)aName;	// silence compiler warning
       
   476 #endif
       
   477 	// Error call removed. Fixes defect IP/76. -MikaL
       
   478 	//Error(KErrNotSupported);
       
   479 	}
       
   480 
       
   481 
       
   482 void CProviderInet6Base::Process(RMBufChain& /*aPacket*/, CProtocolBase* /*aSourceProtocol*/)
       
   483 	{
       
   484 	Panic(EInet6Panic_NotSupported);
       
   485 	}
       
   486 
       
   487 //
       
   488 // Error report routine.
       
   489 //
       
   490 // Soft errors are not immediately reported to the socket server.
       
   491 // A soft error is indicated by a zero aOperationMask.
       
   492 //
       
   493 // The socket error can be cleared by calling this routing with
       
   494 // aError == KErrNone.
       
   495 //
       
   496 void CProviderInet6Base::Error(TInt aError, TUint aOperationMask)
       
   497 	{
       
   498 	if (aError <= KErrNone && !FatalState())
       
   499 		{
       
   500 		iLastError.iStatus = aError;
       
   501 		if (aError == KErrNone)
       
   502 			iErrorMask = aOperationMask;
       
   503 		else
       
   504 			iErrorMask |= aOperationMask;
       
   505 		if (iSocket && aOperationMask)
       
   506 			{
       
   507 			LOG(Log::Printf(_L("\t%S SAP[%u] Error %d, mask %b"),
       
   508 						&ProtocolName(), (TInt)this, aError, aOperationMask));
       
   509 			iSocket->Error(aError, aOperationMask);
       
   510 	 		}
       
   511 		else
       
   512 			{
       
   513 			LOG(Log::Printf(_L("\t%S SAP[%u] Error %d, mask %b pending"),
       
   514 						&ProtocolName(), (TInt)this, aError, aOperationMask));
       
   515 			}
       
   516 		}
       
   517 	else
       
   518 		{
       
   519 		LOG(Log::Printf(_L("\t%S SAP[%u] Error %d, mask %b ignored"),
       
   520 					&ProtocolName(), (TInt) this, aError, aOperationMask));
       
   521 		}
       
   522 	}
       
   523 
       
   524 void CProviderInet6Base::SaveIcmpError(TInt aType, TInt aCode, const TInetAddr& aSrcAddr,
       
   525 									 const TInetAddr& aDstAddr, const TInetAddr& aErrAddr)
       
   526 	{
       
   527 	iLastError.iErrType = aType;
       
   528 	iLastError.iErrCode = aCode;
       
   529 	iLastError.iSrcAddr = aSrcAddr;
       
   530 	iLastError.iDstAddr = aDstAddr;
       
   531 	iLastError.iErrAddr = aErrAddr;
       
   532 	}
       
   533 
       
   534 void CProviderInet6Base::CanSend()
       
   535 	{
       
   536 	if(iSocket && /*iFlow.Status() == EFlow_READY && */!FatalState())
       
   537 		{
       
   538 		LOG(Log::Printf(_L("\t%S SAP[%u] CanSend() Flow UNBLOCKED"), &ProtocolName(), (TInt)this));
       
   539 		iSocket->CanSend();
       
   540 		}
       
   541 	}
       
   542 
       
   543 void CProviderInet6Base::NoBearer(const TDesC8& aConnectionParams)
       
   544 	{
       
   545 	if(iSocket)
       
   546 		{
       
   547 		LOG(Log::Printf(_L("\t%S SAP[%u] NoBearer()"), &ProtocolName(), (TInt)this));
       
   548 		iSocket->NoBearer(aConnectionParams);
       
   549 		}
       
   550 	}
       
   551 
       
   552 void CProviderInet6Base::Bearer(const TDesC8 &aConnectionInfo)
       
   553 	{
       
   554 	if(iSocket)
       
   555 		{
       
   556 		LOG(Log::Printf(_L("\t%S SAP[%u] Bearer()"), &ProtocolName(), (TInt)this));
       
   557 		iSocket->Bearer(aConnectionInfo);
       
   558 		}
       
   559 	}
       
   560 
       
   561 TInt CProviderInet6Base::CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic)
       
   562 	{
       
   563 	return iSecurityChecker ? iSecurityChecker->CheckPolicy(aPolicy, aDiagnostic) : KErrDisconnected;
       
   564 	}
       
   565 
       
   566 TInt CProviderInet6Base::SecurityCheck(MProvdSecurityChecker *aSecurityChecker)
       
   567 	{
       
   568 	iSecurityChecker = aSecurityChecker;
       
   569 	iHasNetworkServices = CheckPolicy(KPolicyNetworkServices, 0) == KErrNone;
       
   570 	return KErrNone;
       
   571 	}
       
   572 
       
   573 TInt CProviderInet6Base::GetOptionInt(const TDesC8 &anOption, TInt &aVal)
       
   574 	{
       
   575  	if (STATIC_CAST(TUint, anOption.Length()) < sizeof(aVal))
       
   576 		return KErrTooBig;
       
   577 	Mem::Copy(&aVal, anOption.Ptr(), sizeof(aVal));
       
   578 	return KErrNone;
       
   579 	}
       
   580 
       
   581 TInt CProviderInet6Base::SetOptionInt(TDes8 &anOption, TInt aVal)
       
   582 	{
       
   583 	if (STATIC_CAST(TUint, anOption.MaxLength()) < sizeof(aVal))
       
   584 		return KErrTooBig;
       
   585 	anOption.SetLength(sizeof(aVal));
       
   586 	anOption.Copy((TUint8*)&aVal, sizeof(aVal));
       
   587 	return KErrNone;
       
   588 	}
       
   589 
       
   590 TInt CProviderInet6Base::Write(RMBufChain& aData, TUint aOptions, TSockAddr* aToAddr)
       
   591 	{
       
   592 	RMBufSendPacket packet;
       
   593 	packet.Assign(aData);	// *beware!* It is legal for aData to be EMPTY!
       
   594 #ifdef _LOG
       
   595 	TBuf<70> tmp(_L("NULL"));
       
   596 #endif
       
   597 
       
   598 	TInt offset = 0;
       
   599 	RMBufSendInfo* info = NULL;
       
   600 	TInt err(0);
       
   601 	// Allocate the info block for the packet.
       
   602 	info = packet.NewInfo();
       
   603 	// Because many RMBufChain methods do not handle the empty 
       
   604 	// chain "logically", must make sure the chain has at least
       
   605 	// one RMBuf in it (without no content). Allocate one and
       
   606 	// make its content empty.
       
   607 	if (info)
       
   608 		{
       
   609 		if (packet.IsEmpty())
       
   610 			{
       
   611 			err = packet.Alloc(0);	// <-- *WARNING* Assumed to allocate single RMBuf
       
   612 			if (err == KErrNone)
       
   613 				{
       
   614 		    	packet.First()->AdjustStart(packet.Length());
       
   615 				info->iLength = 0;
       
   616 				}
       
   617 			}
       
   618 		else
       
   619 			info->iLength = packet.Length();
       
   620 		}
       
   621 	else
       
   622 		err = KErrNoMBufs; // The info allocation was not successful
       
   623 	
       
   624 	
       
   625 	if(err < 0)
       
   626 		{
       
   627 		// Treat all leaves in above as no MBufs.
       
   628 		LOG(Log::Printf(_L("Write\t%S SAP[%u] No Mbufs (%d)"), &ProtocolName(), (TInt)this, err));
       
   629 		err = KErrNoMBufs;
       
   630 		goto notify_error;
       
   631 		}
       
   632 
       
   633 #ifdef _LOG
       
   634 	if (aToAddr)
       
   635 		TInetAddr::Cast(*aToAddr).OutputWithScope(tmp);
       
   636 	Log::Printf(_L("Write\t%S SAP[%u] len=%d, opt=%x, to=%S"), &ProtocolName(), (TInt)this, info->iLength, aOptions, &tmp);
       
   637 #endif
       
   638 
       
   639 	//
       
   640 	// Initialize the info
       
   641 	//
       
   642 	TInetAddr::Cast(info->iSrcAddr).Init(0);
       
   643 	info->iSrcAddr.SetPort(0);
       
   644 	TInetAddr::Cast(info->iDstAddr).Init(0);
       
   645 	info->iDstAddr.SetPort(0);
       
   646 	//
       
   647 	// Get the protocol number to use.
       
   648 	// iProtocolId must be NON-ZERO for anything else, except
       
   649 	// for IP/IP6 raw sockets. Only those sockets have specified
       
   650 	// that the protocol number can be given in port field!
       
   651 	info->iProtocol = iProtocolId != 0 ? iProtocolId :
       
   652 		aToAddr != NULL ? aToAddr->Port() : 0;
       
   653 	info->iFlags = aOptions & (KIpHeaderIncluded | KIpDontFragment);
       
   654 	if (iHeaderIncluded)
       
   655 		info->iFlags |= KIpHeaderIncluded;
       
   656 	(void)new (&info->iFlow) RFlowContext();
       
   657 
       
   658 	//
       
   659 	// Prepare iDstAddr from aToAddr, if specified
       
   660 	//
       
   661 	if (aToAddr)
       
   662 		{
       
   663 		info->iDstAddr = *aToAddr;	// Copy as is, including port, flow label and scope.
       
   664 		if (info->iDstAddr.Family() != KAfInet6)
       
   665 			TInetAddr::Cast(info->iDstAddr).ConvertToV4Mapped();
       
   666 		}
       
   667 	//
       
   668 	// Prepare from included header, if present
       
   669 	//
       
   670 	err = KErrNotSupported;
       
   671 	if (info->iFlags & KIpHeaderIncluded)
       
   672 		{
       
   673 		// The packet starts with an IPv4 or IPv6 header.
       
   674 		TInt next_header = info->iProtocol;
       
   675 		TIpHeader *const ip = ((RMBufPacketPeek &)packet).GetIpHeader();
       
   676 		if (!ip)
       
   677 			{
       
   678 			LOG(Log::Printf(_L("\t%S SAP[%u] HeaderIncluded, short/bad IP header"), &ProtocolName(), (TInt)this));
       
   679 			goto notify_error;
       
   680 			}
       
   681 		switch (ip->ip4.Version())
       
   682 			{
       
   683 			case 4:
       
   684 				offset = ip->ip4.HeaderLength();
       
   685 				// If protocol is ZERO in header, default to aProtocol. This is
       
   686 				// a backward compatibility issue. Applications should not rely
       
   687 				// on this. If they are providing the IPv4 header, they SHOULD
       
   688 				// ALSO fill the proper protocol number in there.
       
   689 				if (!ip->ip4.Protocol())
       
   690 					ip->ip4.SetProtocol(next_header);
       
   691 				else
       
   692 					next_header = ip->ip4.Protocol();
       
   693 				TInetAddr::Cast(info->iSrcAddr).SetV4MappedAddress(ip->ip4.SrcAddr());
       
   694 				if (aToAddr)
       
   695 					ip->ip4.SetDstAddr(TInetAddr::Cast(info->iDstAddr).Address());
       
   696 				else
       
   697 					TInetAddr::Cast(info->iDstAddr).SetV4MappedAddress(ip->ip4.DstAddr());
       
   698 				info->iProtocol = KProtocolInetIp;
       
   699 				break;
       
   700 			case 6:
       
   701 				offset = ip->ip6.HeaderLength();
       
   702 				// Note: ZERO NextHeader() does not cause default processing. In
       
   703 				// IPv6 ZERO is the Hop-by-Hop extension header and potentially
       
   704 				// provided by the application.
       
   705 				next_header = ip->ip6.NextHeader();
       
   706 				TInetAddr::Cast(info->iSrcAddr).SetAddress(ip->ip6.SrcAddr());
       
   707 				if (aToAddr)
       
   708 					ip->ip6.SetDstAddr(TInetAddr::Cast(info->iDstAddr).Ip6Address());
       
   709 				else
       
   710 					TInetAddr::Cast(info->iDstAddr).SetAddress(ip->ip6.DstAddr());
       
   711 				info->iProtocol = KProtocolInet6Ip;
       
   712 				break;
       
   713 			default:
       
   714 				LOG(Log::Printf(_L("\t%S SAP[%u] HeaderIncluded, bad IP version (= %d)"), &ProtocolName(), (TInt)this, (TInt)ip->ip4.Version()));
       
   715 				goto notify_error;
       
   716 			}
       
   717 		//
       
   718 		// Need to locate the upper layer header
       
   719 		//
       
   720 		while (info->iProtocol != next_header)
       
   721 			{
       
   722 			TInet6Packet<TInet6HeaderExtension> hdr(packet, offset);
       
   723 			if (hdr.iHdr == NULL || !TPacketPoker::IsExtensionHeader(next_header))
       
   724 				{
       
   725 				LOG(Log::Printf(_L("\t%S SAP[%u] HeaderIncluded, unknown extension hdr (= %d)"), &ProtocolName(), (TInt)this, next_header));
       
   726 				goto notify_error;				
       
   727 				}
       
   728 			offset += hdr.iHdr->HeaderLength();
       
   729 			next_header = hdr.iHdr->NextHeader();
       
   730 			}
       
   731 		}
       
   732 
       
   733 	iFlow.SetProtocol(info->iProtocol);
       
   734 	err = DoWrite(packet, *info, aOptions, offset);
       
   735 	if (err == KErrNone)
       
   736 		{
       
   737 		// If packet is Empty, assume DoWrite handled it, and
       
   738 		// don't send it to the protocol.
       
   739 		if (!packet.IsEmpty())
       
   740 			{
       
   741 			packet.Pack();
       
   742 			iProtocol->Send(packet);
       
   743 			}
       
   744 		goto packet_done;
       
   745 		}
       
   746 	// DoWrite indicated problem:
       
   747 	//	 err > 0, flow cannot receive packet
       
   748 	//	 err < 0, some error condition
       
   749 	//
       
   750 notify_error:
       
   751 	if (err >= 0)
       
   752 		err = 0;	// Return 0 to indicate that packet has not been accepted
       
   753 	else if (err != KErrNoMBufs)
       
   754 		{
       
   755 		//
       
   756 		// Cannot send the packet, report error and drop packet.
       
   757 		//
       
   758 		Error(err, MSocketNotify::EErrorSend);
       
   759 		goto packet_done;
       
   760 		}
       
   761 	else
       
   762 		{
       
   763 		if (iSynchSend == 0)
       
   764 			{
       
   765 			// Out of buffer space (KErrNoMBufs). If iSynchSend is not set, just
       
   766 			// drop the packet silently,
       
   767 			LOG(Log::Printf(_L("\t%S SAP[%u] Dropping packet for KErrNoMBufs"), &ProtocolName(), (TInt)this));
       
   768 			goto packet_done;
       
   769 			}
       
   770 		LOG(Log::Printf(_L("\t%S SAP[%u] Blocking for KErrNoMBufs"), &ProtocolName(), (TInt)this));
       
   771 		}
       
   772 
       
   773 	// note: err == 0 or KErrNoMBufs!
       
   774 	aData.Assign(packet);	// Try to return original chain (approximately correct only
       
   775 							// if DoWrite does not add anything to the chain!)
       
   776 	packet.Free();			// Need to release info!
       
   777 	return err;
       
   778 packet_done:
       
   779 	// Packet has been sent or dropped
       
   780 	packet.Free();			// Cleanup, not always needed (does nothing then).
       
   781 	return 1;				// Return 1 to indicate that packet has been accepted
       
   782 	}
       
   783 
       
   784 TUint CProviderInet6Base::Write(const TDesC8& aDesc, TUint aOptions, TSockAddr* aAddr)
       
   785 	{
       
   786 	LOG(Log::Printf(_L("Write\t%S SAP[%u] Desclen=%d, opt=%x)"), &ProtocolName(), (TInt)this, aDesc.Length(), aOptions));
       
   787 	RMBufChain data;
       
   788 	if (aDesc.Length() > 0)
       
   789 		{
       
   790 		TRAPD(err, data.CreateL(aDesc));
       
   791 		if (err != KErrNone)
       
   792 			{
       
   793 			data.Free();	// just to be sure..
       
   794 			return 1;
       
   795 			}
       
   796 		}
       
   797 	const TInt ret = Write(data, aOptions, aAddr) != 0; // Return 0 or 1 only.
       
   798 	data.Free();
       
   799 	return ret;
       
   800 	}