/*
* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/


#include <sys/types.h>
#include <string.h>		// for memcpy
#include <fcntl.h>		// for struct stat
#include <sys/errno.h>		// for ENOTSOCK
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <netinet/in.h>		// for htons
#include <sys/sockio.h>
#include <bt_sock.h>     // Symbian BT constantss needed for cooperation with Symbian sockets
#include <arpa/inet.h>   
#include <es_sock.h>
#include <in_sock.h>
#include <net/if.h>
#include <commdb.h>
#include <cdbcols.h>
#include <commdbconnpref.h>
#include <e32base.h>
#include <e32err.h>
#include <utf.h>
#include <e32std.h>
#include <net/route.h>
#include <in_iface.h>
#include "fdesc.h"
#include "lposix.h"
#include "sysif.h"

// Support for struct sockaddr conversion
TUSockAddr::TUSockAddr (TAny* aBuf) 
: TSockAddr(), iError(0)
		{
		Prepare(aBuf);
		}

void TUSockAddr::Prepare (TAny* aBuf) 
//
// Prepare a TUSockAddr to receive an address (used in RecvFrom)
// Setting the length to 0 indicates that we don't really want this address anyway.
//
	{
	if (aBuf==0)
		{
		SetLength(0);
		iError = EFAULT;
		return;
		}
	}

EXPORT_C TUSockAddr::TUSockAddr (const TAny* aBuf, TUint aLen) 
: TSockAddr(), iError(0)
		{
		Set(aBuf,aLen);
		}

void TUSockAddr::Set (const TAny* aBuf, TUint aLen) 
//
// Construct an ESOCK TSockAddr from a struct sockaddr.
// We have to deal with the network byte ordering of AF_INET addresses
//
	{
	if (!aBuf)
		{
		iError = EFAULT;
		SetLength(0);
		return;
		}
	
	const TUint dataOffset = (TUint)&((struct sockaddr *)0)->sa_data[0];
	// aLen should be atleast have minimum size.
	if (aLen < dataOffset)
		{
		iError = EINVAL;
		SetLength(0);
		return;
		}

	const struct sockaddr* sp= (const struct sockaddr *)(aBuf);
	TUint8 *from=(TUint8*)aBuf;	

	if (sp->sa_family==AF_INET)
		{		
		// byte-swap sockaddr_in back into host ordering
		TUint port=(from[2]<<8)+from[3];
		from+=4;
		TUint32 addr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
		from+=4;
		SetFamily(AF_INET);
		SetPort(port);
		*(TUint32*)UserPtr()=addr;
		SetUserLen(4);
		return;
		}
	else if (sp->sa_family == AF_INET6)
		{
		SetFamily(sp->sa_family);
		SetPort(ByteOrder::Swap16(sp->sa_port));
		from+=4;
		// copy the rest of the data as given
		TUint8 *to=UserPtr();
		if (aLen<4)
			aLen=4;
		aLen-=4;	// skip fmaily and port
		if (aLen>24)
			aLen=24;
		memcpy(to,from,aLen);
		SetUserLen(aLen);    	
		return;
		}	
	else if (sp->sa_family == KBTAddrFamily)
		{
		// Make a TBTSockAddr from a sockaddr_bt...
		TBTSockAddr tmpAddr;

		// Family is always Bluetooth:
		tmpAddr.SetFamily(KBTAddrFamily);

		// The port number has the correct byte order already, as the
		// POSIX Bluetooth APIs assume litle-endian format:
		tmpAddr.SetPort(sp->sa_port);

		// For the address we need to reverse the byte ordering, as
		// Symbian appears to index Bluetooth addresses in a
		// big-endian manner:

		const TInt KBTAddrLength = 6;  // Bytes in a Bluetooth address
		const TInt KBTAddrOffset = 4;  // Offset of address in sockaddr_bt

		TBTDevAddr devAddr;
		const TInt KMinLength = KBTAddrLength + KBTAddrOffset;

		if (aLen >= KMinLength)
			{
			for (TInt i=0; i<KBTAddrLength; ++i)
				{
				devAddr[i] = from[KMinLength - 1 - i];
				}
			}

		tmpAddr.SetBTAddr(devAddr);

		// Security settings:
		TBTServiceSecurity sec;
		sec.SetUid(TUid::Uid(0));
		sec.SetAuthentication(EFalse);
		sec.SetEncryption(EFalse);
		sec.SetAuthorisation(EFalse);
		sec.SetDenied(EFalse);
		tmpAddr.SetSecurity(sec);

		// Now we must copy the contents of the "tmpAddr" TBTSockAddr,
		// but unfortunately there isn't an assignment operator for us
		// to use. Still, we know it is a self-contained T class for
		// which a direct shallow copy using memcopy() will be ok:
		//
		memcpy(this, &tmpAddr, sizeof(TBTSockAddr));

		return;
		}
	else
		{
		// Not AF_INET or KBTAddrFamily:

		// expand the family and port
		SetFamily(sp->sa_family);
		SetPort(sp->sa_port);
		from+=4;
		// copy the rest of the data as given
		TUint8 *to=UserPtr();
		if (aLen<4)
			aLen=4;
		aLen-=4;	// skip fmaily and port
		if (aLen>24)
			aLen=24;
		memcpy(to,from,aLen);
		SetUserLen(aLen);
		}
	}

/*
 * Extract a struct sockaddr from a TSockAddr
 */
EXPORT_C void TUSockAddr::Get(TAny* addr, unsigned long* len)
	{
	if (addr==0)
		{
		iError = EFAULT;
		SetLength(0);
		return;
		}
	const TUint dataOffset = (TUint)&((struct sockaddr *)0)->sa_data[0];
	// aLen should be atleast have minimum size.
	if (*len < dataOffset)
		{
		iError = EINVAL;
		SetLength(0);
		return;
		};

	struct sockaddr* sp=(struct sockaddr*)addr;
	TUint16 port=(TUint16)Port();

	//The ipv4 address could be obtained either as
	//plain 32 bit address or as ipv4 mapped ipv6 address
	TInetAddr inetAddr(*this);
	TBool isV4Mapped = (Family()==AF_INET6) && (inetAddr.IsV4Mapped() || inetAddr.IsV4Compat());
	if (Family()==AF_INET || isV4Mapped)
		{
		sp->sa_family=AF_INET;
		sp->sa_port= ByteOrder::Swap16(port);
		TUint8* from=UserPtr();
		TUint32 fromaddr;
		//If the address is v4 mapped, we take the last 4 bytes from the 16 bytes long v6 structure. 
		if(isV4Mapped)
			fromaddr = (from[15]<<24)+(from[14]<<16)+(from[13]<<8)+from[12];
		else
			fromaddr = (from[0]<<24)+(from[1]<<16)+(from[2]<<8)+ from[3];
		unsigned char * ptr = (unsigned char *)&fromaddr;
		sp->sa_data[0] =  ptr[0];
		sp->sa_data[1] =  ptr[1];
		sp->sa_data[2] =  ptr[2];
		sp->sa_data[3] =  ptr[3];
		*len=8;
		return;
		}
	else if (Family()==AF_INET6)
		{

		sp->sa_family=(TUint16)Family();
		sp->sa_port=ByteOrder::Swap16(port);
		TUint ulen=GetUserLen();
		if (ulen+4>(*len))
			ulen=(*len)-4;
		*len=ulen+4;
		memcpy(sp->sa_data,UserPtr(),ulen);
		sp->sa_len = ulen;
		return;
		}		
	else if (Family()==KBTAddrFamily)
		{
		sp->sa_family=KBTAddrFamily;
		sp->sa_port=port;

		const TInt KBTAddrLength = 6;
		if (GetUserLen() == KBTAddrLength)
			{
			for (TInt i=0; i<KBTAddrLength; ++i)
				{
				sp->sa_data[KBTAddrLength - 1 - i] = UserPtr()[i];
				}
			}
		return;
		}
	else
		{
		// Not AF_INET or KBTAddrFamily:
		sp->sa_family=(TUint16)Family();
		sp->sa_port=port;
		TUint ulen=GetUserLen();
		if (ulen+4>(*len))
			ulen=(*len)-4;
		*len=ulen+4;
		memcpy(sp->sa_data,UserPtr(),ulen);
		}
	}

// The Socket descriptor class
CSocketDesc::CSocketDesc()
:iIoctlBuf(0,0),
iSocketPtr(NULL),
iConnPref(),
iConnectionPtr(NULL),
iSubConnectionPtr(NULL),
iRConnectionIndex(-1),		
iSockServPtr(NULL)
		{

		};


TInt CSocketDesc::Socket(RSocketServ& aSs, int family, int style, int protocol)
	{
	if (protocol == 0)
		{
		if (family == AF_INET)
			{
			switch (style)
				{
				case SOCK_STREAM:
					protocol = IPPROTO_TCP;
					break;

				case SOCK_DGRAM:
					protocol = IPPROTO_UDP;
					break;
				}
			}
		else
			{
			protocol = KUndefinedProtocol;
			}
		}

	iFcntlFlag = 0;
	TInt err = CreateLock();
	if (err)
		{
		return err;
		}

	if (family == AF_INET6)
		{
		err = iSocket.Open(aSs, KAfInet, style, protocol);
		}
	else
		{
		err = iSocket.Open(aSs, family, style, protocol);
		}

	if (err == KErrNone)
		{
		iStyle = style;
		iSocket.Close(); // We will close now, to open later using connection preferences
		iAddrFamily = family;
		iProtocol = protocol; 
		iSockServPtr = &aSs; // Saving the const session pointer for later use
		}
	return err;
	}

TInt CSocketDesc::FinalClose()
	{
	CLocalSystemInterface* backend = Backend();
	backend->DefConnLock().Wait();
	RHeap* oheap = User::SwitchHeap(backend->Heap());	
	if (iSocketPtr != NULL)
		{
		iSocketPtr = NULL;	
		StopInterface(NULL); // Checks for RConnection as well as RSubConnection
	    backend->RemoveSocket(this);
		}

	CSockDescBase::FinalClose();
	User::SwitchHeap(oheap);
	backend->DefConnLock().Signal();
	return KErrNone;
	}


void CSocketDesc::Read (TDes8& aBuf, TRequestStatus& aStatus)
	{
	//Acquire the Lock before read and release it later
	iReadLock.Wait();
	if (iSocketPtr == NULL)
		{
		TInt ret = OpenUsingPreference();
		if (ret != KErrNone)	// Error in open
			{
			Complete(aStatus,ret);
			iReadLock.Signal();
			return;
			}
		}
	CSockDescBase::Read (aBuf,aStatus);
	iReadLock.Signal();
	}

TInt CSocketDesc::ReadCompletion(TDes8& aBuf, TInt aStatus)
	{
	return CSockDescBase::ReadCompletion(aBuf, aStatus);
	}

void CSocketDesc::ReadCancel()
	{
	if (iSocketPtr != NULL)
		{
		CSockDescBase::ReadCancel();
		}
	}

void CSocketDesc::Write (TDes8& aBuf, TRequestStatus& aStatus)
	{

    TInt err = maybe_reopen_socket();
    if (err != KErrNone)
        {
        Complete(aStatus, err);
        return;
        }
	
	iWriteLock.Wait();
	CSockDescBase::Write(aBuf, aStatus);
	iWriteLock.Signal();	
	}

void CSocketDesc::WriteCancel()
	{
	if (iSocketPtr != NULL)
		{
		CSockDescBase::WriteCancel();
		}
	}


TInt CSocketDesc::Bind(const struct sockaddr* aAddr, unsigned long aSize)
	{
	TInt ret;
	TUSockAddr addr(aAddr,aSize);

	if (addr.iError != 0)
		{
		return addr.iError;
		}
	
	ret = maybe_reopen_socket();
	if (ret != KErrNone)
	    return ret;
	ATOMICSOCKETOP(ret = iSocket.Bind(addr),return KErrBadHandle)
	return ret;
	}

TInt CSocketDesc::Listen(TUint qSize)
	{

    TInt ret;
	if (iStyle == SOCK_DGRAM) // Listen on UDP socket, crashing at RSocket::Listen().
		{
		return EOPNOTSUPP;
		}
	
	ret = maybe_reopen_socket();
	if (ret != KErrNone)
	    return ret;

	return CSockDescBase::Listen(qSize);
	}

TInt CSocketDesc::SockName(int anEnd, struct sockaddr* anAddr,unsigned long* aSize)
	{


	if (!anAddr)
        {
        return EFAULT;
        }

	TInt ret = maybe_reopen_socket();
	if (ret != KErrNone)
	    return ret;
	
   
    struct sockaddr temp;
    unsigned long len = sizeof( temp );
    
	TUSockAddr nSockAddr(&temp, len );

	ret = CSockDescBase::SockName(anEnd,nSockAddr);
	if(ret == KErrNone )
	    {
            nSockAddr.Get(&temp,&len );
            if( *aSize > len )
                *aSize = len;
            memcpy( anAddr,&temp,*aSize);
            
            }
	
	return ret;
	}

TInt CSocketDesc::GetSockOpt(TInt anOptionName, TInt anOptionLevel, TDes8& anOption)
	{
	TInt ret;
	if (anOption.Ptr() == NULL)
		{
		return EFAULT;
		}
	if (anOption.Length() == 0)
		{
		return EINVAL;
		}
	
	ret = maybe_reopen_socket();
	if (ret != KErrNone)
	    return ret;

	if (SO_TYPE == anOptionName && SOL_SOCKET == anOptionLevel)
		{
		TProtocolDesc protocolInfo;
		ATOMICSOCKETOP(ret = iSocket.Info(protocolInfo), ret = KErrBadHandle)
		if (KErrNone == ret )
			{
			// Copy the Socket Type to the buffer
			TInt size = (anOption.Length() < sizeof(protocolInfo.iSockType))? anOption.Length(): sizeof(protocolInfo.iSockType);
			Mem::Copy((unsigned char*)anOption.Ptr(), &protocolInfo.iSockType, size);
			anOption.SetLength(size);
			}
		return ret;
		}

	if(IPPROTO_IP == anOptionLevel && IP_MULTICAST_IF == anOptionName)
		{
		TUSockAddr addr;
		struct sockaddr_in sockAddress;
		sockAddress.sin_family = AF_INET;
		ATOMICSOCKETOP(sockAddress.sin_port = iSocket.LocalPort(),return KErrBadHandle)			
		ATOMICSOCKETOP(iSocket.LocalName(addr);,return KErrBadHandle)		
		TInt a = sizeof(sockAddress);
		addr.Get(&sockAddress,(unsigned long*)&a);  
		TInt size = (anOption.Length() < sizeof(sockAddress.sin_addr))? anOption.Length(): sizeof(sockAddress.sin_addr);
		Mem::Copy((unsigned char*)anOption.Ptr(), &(sockAddress.sin_addr), size); 
		anOption.SetLength(size);
		return KErrNone;
		}

	switch(anOptionLevel)
		{
		case IPPROTO_TCP:
			anOptionLevel=SOL_TCP;
			break;
		case IPPROTO_IP:
			anOptionLevel=SOL_IP;
			break;
		case SOL_SOCKET:
			{
			switch(anOptionName)
				{
				case SO_REUSEADDR: 
					anOptionLevel=SOL_IP;
					break;
				case SO_OOBINLINE:
				case SO_KEEPALIVE:
					anOptionLevel=SOL_TCP;
					break; 
				case SO_BROADCAST:
					*((TInt*)anOption.Ptr()) = 1;
					return KErrNone;
				}
			}
		} 

	switch(anOptionName)
		{
		case IP_MULTICAST_TTL:
			anOptionLevel=KSolInetIp;
			anOptionName=KSoIp6MulticastHops;
			break;
		case IP_MULTICAST_LOOP:
			anOptionLevel=KSolInetIp;
			anOptionName=KSoIp6MulticastLoop;
			break;
		}
	ATOMICSOCKETOP(ret = iSocket.GetOpt(anOptionName,anOptionLevel,anOption), return KErrBadHandle)
	return ret;
	}

TInt CSocketDesc::GetInterfaceIndex(TUint32 anAddr)
	{
	TPckgBuf<TSoInetIfQuery> ifq;
	TInt aIndex = -1;
	if (KInetAddrAny == anAddr)
		{
		aIndex = 0;
		return aIndex;
		}
	else 
		{
		TInt ret = KErrNone;
		ATOMICSOCKETOP(ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle)
		if (ret != KErrNone)
			return KErrGeneral;

		TPckgBuf<TSoInetInterfaceInfo>iface;
		ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, iface), ret = KErrBadHandle )
		while(ret == KErrNone)
			{
			TSoInetInterfaceInfo &info = iface();
			TInt result;
			if(info.iState == EIfUp)
				{
				if (anAddr == info.iAddress.Address()) 
					{      	
					ifq().iName = info.iName;
					ATOMICSOCKETOP( result = iSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifq), result = KErrBadHandle )
					if (result == KErrNone)
						aIndex = ifq().iIndex;

					}
				}
			ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, iface), ret = KErrBadHandle )
			}   	
		}
	return aIndex;
	}

TInt CSocketDesc::SetSockOpt(TInt anOptionName, TInt anOptionLevel, TDesC8& anOption)
	{
	TInt ret;
	if (anOption.Ptr() == NULL)
		{
		return EFAULT;
		}
	if (anOption.Length() == 0)
		{
		return EINVAL;
		}
	
	ret = maybe_reopen_socket();
	if (ret != KErrNone)
	    return ret;

	switch(anOptionLevel)
		{
		case IPPROTO_TCP:
			anOptionLevel=SOL_TCP;
			break;
		case IPPROTO_IP:
			anOptionLevel=SOL_IP;
			break;
		case SOL_SOCKET:
			{
			switch(anOptionName)
				{
				case SO_REUSEADDR: 
					anOptionLevel=SOL_IP;
					break;
				case SO_OOBINLINE:
				case SO_KEEPALIVE:
					anOptionLevel=SOL_TCP;
					break; 
				}
			}

		}
	TPckgBuf<TIp6Mreq> req;
	struct ip_mreq *mreq;
	TInt aIndex = -1;
	TUint8 *from;
	TUint32 srcAddr;
	TUint32 maddr;
	TInetAddr multiAddr;
	TInt *Option = NULL;
	TInt ttlValue = 0;
	switch(anOptionName) 
		{
		case IP_ADD_MEMBERSHIP:  //KSoIp6JoinGroup
		case IP_DROP_MEMBERSHIP: //KSoIp6LeaveGroup

			mreq = (struct ip_mreq *)anOption.Ptr();
			from = (TUint8 *)anOption.Ptr(); 
			from+=4;
			// swaping the byte order
			srcAddr = ByteOrder::Swap32( mreq->imr_interface.s_addr); 
			//fetch the interface index
			aIndex = GetInterfaceIndex(srcAddr);

			// Set the multicast addr
			from = (TUint8 *)anOption.Ptr();
			maddr=(from[0]<<24)+(from[1]<<16)+(from[2]<<8)+from[3];
			multiAddr.SetAddress( maddr);
			multiAddr.ConvertToV4Mapped();
			if (multiAddr.IsMulticast())
			    {
                req().iAddr = multiAddr.Ip6Address();
                req().iInterface = aIndex;  
			    }
			ATOMICSOCKETOP( ret = iSocket.SetOpt(anOptionName, anOptionLevel, req), return KErrBadHandle )
			return ret;

		case IP_MULTICAST_TTL:
			anOptionLevel=KSolInetIp;
			anOptionName=KSoIp6MulticastHops;
			Option = (TInt*)anOption.Ptr();
			ttlValue = *Option;
			ATOMICSOCKETOP( ret = iSocket.SetOpt(anOptionName,anOptionLevel,ttlValue), return KErrBadHandle )
			return ret;
			
		case SO_BROADCAST: 
			//check if user is trying to disable broadcast
			Option = (TInt*)anOption.Ptr();
			return (*Option == 0 ? KErrNotSupported : KErrNone);

		case IP_MULTICAST_IF:
			{
			//No support for equivalent flag KsoIp6MulticastIf presently
			//call bind instead	    
			struct in_addr *inAddress = (struct in_addr*)anOption.Ptr();	    
			struct sockaddr_in sockAddress; 	 		    
			sockAddress.sin_family = AF_INET;
			ATOMICSOCKETOP(sockAddress.sin_port = iSocket.LocalPort();,return KErrBadHandle)         
			sockAddress.sin_addr.s_addr = inAddress->s_addr;
			TUSockAddr ifAddress(&sockAddress, sizeof(sockAddress));
			ATOMICSOCKETOP( ret = iSocket.Bind(ifAddress), return KErrBadHandle )
			return ret;
			}

		case IP_MULTICAST_LOOP:
			anOptionLevel=KSolInetIp;
			anOptionName=KSoIp6MulticastLoop;
			break;	    	



		}
	ATOMICSOCKETOP( ret = iSocket.SetOpt(anOptionName,anOptionLevel,anOption), return KErrBadHandle )
	return ret;
	}

void CSocketDesc::Sync (TRequestStatus& aStatus)
	{
	// Judging from the Solaris man pages, this does nothing.
	Complete(aStatus,KErrNone);
	}

void CSocketDesc::RecvFrom(TDes8& aDesc, TSockAddr& from, int flags, TRequestStatus& aStatus)
	{
    TInt err = maybe_reopen_socket();
    if (err != KErrNone)
        {
        Complete(aStatus, err);
        return;
        }

	iReadLock.Wait();
	CSockDescBase::RecvFrom(aDesc, from, flags, aStatus);
	iReadLock.Signal();
	}

void CSocketDesc::RecvFromCancel()
	{
	if (iSocketPtr != NULL)
		{
		CSockDescBase::RecvFromCancel();
		}
	}


void CSocketDesc::SendTo(TDes8& aDesc, const struct sockaddr* anAddr, unsigned long aAddrLen, int flags, TRequestStatus& aStatus)
	{
    TInt err = maybe_reopen_socket();
    if (err != KErrNone)
        {
        Complete(aStatus, err);
        return;
        }
    
	TUSockAddr toAddr(anAddr, aAddrLen);
	
	iWriteLock.Wait();  
	CSockDescBase::SendTo(aDesc, toAddr, flags, aStatus);
	iWriteLock.Signal();
	}

void CSocketDesc::SendToCancel()
	{
// Should we use atomic loads here?
	if (iSocketPtr != NULL)
		{
		CSockDescBase::SendToCancel();
		}
	}

void CSocketDesc::Shutdown(TUint aHow,TRequestStatus& aStatus)
	{

    if (__e32_atomic_load_acq32(&iSocketPtr) == NULL) // Not opened at all. Nothing to do.
		{
		Complete(aStatus,KErrNone);
		return;
		}

	CSockDescBase::Shutdown(aHow,aStatus);
	return;
	}

void CSocketDesc::Accept(CFileDescBase*& aNewSocket, TRequestStatus& aStatus, RSocketServ& aSs, TSockAddr * /*aAddr*/)
	{
    aNewSocket = NULL;
	TInt err = maybe_reopen_socket();
	if (err != KErrNone)
	    {
        Complete(aStatus, err);
        return;
	    }
	
	iReadLock.Wait();
	// what are the below coverity thingummichs?
	//coverity[alloc_fn]
	//coverity[assign]
	CSocketDesc *newSocket = new CSocketDesc;
	if (!newSocket)
	    {
        Complete(aStatus, KErrNoMemory);
        iReadLock.Signal();
        return;
	    }
	
	err = newSocket->CreateLock();
	if (err)
		{
        Complete(aStatus, KErrNoMemory);
        delete newSocket;
        iReadLock.Signal();
        //coverity[memory_leak]
        return;
		}

	err = newSocket->iSocket.Open(aSs);
	if (err)
		{
		Complete(aStatus, err);
		newSocket->FinalClose();  // this will Close locks
		delete newSocket;

		iReadLock.Signal();
		//coverity[memory_leak]
		return;
		}
	newSocket->iSocketPtr = &newSocket->iSocket;
	newSocket->iStyle = iStyle;
	err = KErrNone;
	ATOMICSOCKETOP( iSocket.Accept(newSocket->iSocket,aStatus), err = KErrBadHandle )
	if( err )
	    {
	    Complete(aStatus, err);
	    newSocket->FinalClose();  // this will Close locks
	    delete newSocket;
	    }
	else
	    {
	    aNewSocket = newSocket;
	    }
	iReadLock.Signal();
	}

void CSocketDesc::AcceptCancel()
	{
	if (iSocketPtr != NULL)
		{
		ATOMICSOCKETOP( iSocket.CancelAccept(), NOP )
		}
	}

void CSocketDesc::Connect(const struct sockaddr* aAddr,unsigned long size,TRequestStatus& aStatus)
	{
	TUSockAddr addr(aAddr,size);

	if (addr.iError != 0)
		{
		aStatus = addr.iError;
		return;
		}
	
	TInt err = maybe_reopen_socket();
	if (err != KErrNone)
	    {
        aStatus = err;
        return;
	    }
	
	iWriteLock.Wait();
	if( GetConnectionProgress() == EFalse )
	    {
		ATOMICSOCKETOP(iSocket.Connect(addr, aStatus), Complete(aStatus,KErrBadHandle))
	    User::WaitForRequest(aStatus);
	    if( aStatus.Int() == KErrWouldBlock )
	        SetConnectionProgress(ETrue);
	    }
	else
	    {
	    aStatus = EALREADY;
	    }
	iWriteLock.Signal();
	}

void CSocketDesc::ConnectCancel()
	{
	if (iSocketPtr != NULL)
		{
		ATOMICSOCKETOP(iSocket.CancelConnect(),NOP)
		}
	}

void CSocketDesc::Ioctl(int aCmd, void* aParam, TRequestStatus& aStatus)
	{
	TInt ret = KErrNone;
	int* param = reinterpret_cast<int*>(aParam);

	ret = maybe_reopen_socket();
	if (ret != KErrNone)
	    {
        Complete(aStatus, ret);
        return;
	    }

	switch ((unsigned)aCmd)
		{
		case FIONREAD:
		case E32IONREAD:
		    {
			ATOMICSOCKETOP( ret=iSocket.GetOpt(KSOReadBytesPending,KSOLSocket,*param), ret = KErrBadHandle )
		    }
			break;
		case E32IOSELECT:
			{
			iIoctlBuf.Set((TText8*)aParam,4,4);
			iIoctlLock.Wait();
			iIoctlFlag = ETrue;		
			ATOMICSOCKETOP(iSocket.Ioctl(KIOctlSelect,aStatus,&iIoctlBuf,KSOLSocket), Complete(aStatus,KErrBadHandle))
			}
			return;
		case SIOCGIFCONF:
			ret = GetInterfaceList(aParam);
			break;
		case SIOCGIFINDEX:
			ret = GetInterfaceIndexByName(aParam);
			break;
		case SIOCGIFACTIVECONF:
			ret = GetActiveInterfaceList(aParam);
			break;
		case SIOCSIFNAME:
			ret = SetInterfaceByName(aParam);
			break;
		case SIOCIFSTART:
			ret = StartInterface(aParam);
			if(KErrNone == ret)
				{
				iSocket.Close();
				iSocketPtr = NULL;
				}
			break;
		case SIOCIFACTIVESTART:
			ret = StartActiveInterface(aParam);
			if(KErrNone == ret)
				{
				iSocket.Close();
				iSocketPtr = NULL;
				}
			break;
		case SIOCIFSTOP:
			ret = StopInterface(aParam);
			break;	
		case SIOCATMARK:
			ATOMICSOCKETOP(ret=iSocket.GetOpt(KSoTcpRcvAtMark,KSolInetTcp,*param), ret = KErrBadHandle)
			break;	
		case SIOCGIFADDR:
		    ret = GetInterfaceAttributes(aParam, EACTIVE_GETIP);
			break;	
		case SIOCGIFNUM:
			ret = GetInterafceNumber(aParam);
			break;	
		case SIOCADDRT:
			ret = RouteRequest(KSoInetAddRoute, aParam);
			break;	
		case SIOCDELRT:		
			ret = RouteRequest(KSoInetDeleteRoute, aParam);
			break;	
		case SIOCGIFHWADDR:
			ret = GetInterfaceHWAddress(aParam);
		    break;
		case SIOCGIFACTIVEIAP:
		    ret = GetActiveInterface( aParam);
		    break;
		case SIOCGIFFLAGS:
		    ret = GetInterfaceAttributes(aParam, EACCESS_GETFLAGS);
		    break;
		case SIOCGIFMTU:
		    ret = GetInterfaceAttributes(aParam, EACCESS_GETMTU);
		    break;
		case SIOCGIFNETMASK:
		    ret = GetInterfaceAttributes(aParam, EACCESS_GETNETMASK);
		    break;
		case SIOCGIFDEFGATEWAY:
		    ret = GetInterfaceAttributes(aParam, EACCESS_GETDEFGATEWAY);
		    break;

		case SIOCSIFMTU:
		    ret = SetInterfaceAttributes(aParam, EACCESS_SETMTU);
		    break;
		 case SIOCENUMROUTES:
            ret = EnumerateRoutes(aParam);
            break;
		 case SIOCSETDNSSUFFIX:
		     ret = SetInterfaceAttributes(aParam, EACCESS_SETDNSSUFFIX);
			 break;
		 case SIOCGETDNSSUFFIX:
		     ret = GetInterfaceAttributes(aParam, EACCESS_GETDNSSUFFIX);
		     break;
		 case SIOCSNAMESERVER:
		     ret = SetNameServer(aParam,EACCESS_SETNAMESERVERS );
		     break;
		 case SIOCGNAMESERVER:
		     ret = GetNameServer(aParam, EACCESS_GETNAMESERVERS);
             break;
		default:
			ret=KErrNotSupported;
			break;
		}
	Complete(aStatus,ret);
	}

TInt CSocketDesc::IoctlCompletion(int /*aCmd*/, void* /*aParam*/, TInt aStatus)
	{
	if(iIoctlFlag)
		{
		iIoctlLock.Signal();
		iIoctlFlag = EFalse;
		}
	return aStatus;
	}

void CSocketDesc::IoctlCancel()
	{
	if (iSocketPtr && iIoctlFlag)
		{
		ATOMICSOCKETOP(iSocket.CancelIoctl(), NOP)
		iIoctlLock.Signal();
		iIoctlFlag = EFalse;
		}
	}
// -----------------------------------------------------------------------------
// CSocketDesc::Fcntl
// Symbian Socket Specific Implementation for fcntl
// Implementation of fcntl for Socket will make use of  
// RSocket::SetOpt(KSONonBlockingIO/KSOBlockingIO, KSOLSocket)
// As of now fcntl supports F_SETFL and F_GETFL
// -----------------------------------------------------------------------------
//
TInt CSocketDesc::Fcntl(TUint anArg, TUint aCmd)
	{

    TInt err = maybe_reopen_socket();
    if (err != KErrNone)
        return err;

    return CSockDescBase::Fcntl(anArg, aCmd);
	}
/*
TInt CSocketDesc :: GetIpAddress( void *aParam )
	{
	TInetAddr myAddr;
	ATOMICSOCKETOP( iSocket.LocalName(myAddr), return KErrBadHandle )
	TUint32 myIP = myAddr.Address();			
	if (myIP == 0)
		{
		return KErrGeneral;
		}

	ifreq *ifr = (ifreq *)aParam;
	((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr = myIP;
	return KErrNone;
	}*/

TInt CSocketDesc :: GetRemoteIpAddress( void *aParam )
	{
	TInetAddr remoteAddr;
	ATOMICSOCKETOP( iSocket.RemoteName(remoteAddr), return KErrBadHandle )
	TUint32 remoteIP = remoteAddr.Address();			

	if (remoteIP == 0)
		{
		return KErrGeneral;
		}
	ifreq *ifr = (ifreq *)aParam;
	((struct sockaddr_in *)&ifr->ifr_dstaddr)->sin_addr.s_addr = remoteIP;
	return KErrNone;
	}

TInt CSocketDesc :: GetInterafceNumber( void *aParam )
	{
	TInt count = 0;	
	TInt ret = KErrNone;
	TRAP(ret, AccessPointCountL(count));
	*(TInt *)aParam = count;
	return ret;	
	}

#ifdef __SYMBIAN_COMPILE_UNUSED__
TInt CSocketDesc :: GetInterafceParamInfo( void *aParam,TInt aType)
	{
	TInt ret = KErrNone;	
	TAccessPointRecord tempRecord;
	ifreq *ifr = (ifreq *)aParam;
	TRAP(ret,FindConnectionInfoL(tempRecord,ifr->ifr_name));
	if(ret != KErrNone)
		return ret;
	wchar_t *str = (wchar_t *)( tempRecord.iServiceType.PtrZ());	 
	TInt servFlag = 0;
	if(WcsCmp(str,L"LANService") == 0)
		{
		servFlag = 0;
		}
	else if(WcsCmp(str,L"OutgoingGPRS") == 0)
		{
		servFlag  = 1;	
		}
	if(aType == EACCESS_GETMETRIC)
		{
		ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETMETRIC);					
		}	
	else if(aType == EACCESS_GETMTU)
		{
		ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETMTU);					
		}
	else if(aType == EACCESS_GETNETMASK)
		{
		ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETNETMASK);					
		}
	else if(aType == EACCESS_GETBROADCAST)
		{
		ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETBROADCAST);					
		}
	else if(aType == EACCESS_GETPHYSADDR)
		{
		ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETPHYSADDR);					
		}
	else if(aType == EACCESS_GETFLAGS)
		{
		ret = GetInterfaceDetails(aParam,servFlag,EACCESS_GETFLAGS);					
		}
	return ret;	
	}

TInt CSocketDesc :: SetInterafceParamInfo( void *aParam,TInt aType)
	{
	TInt ret = KErrNone;	
	TAccessPointRecord tempRecord;
	ifreq *ifr = (ifreq *)aParam;
	TRAP(ret,FindConnectionInfoL(tempRecord,ifr->ifr_name));
	if(ret != KErrNone)
		return ret;
	wchar_t *str = (wchar_t *)(tempRecord.iServiceType.PtrZ());	 
	TInt servFlag = 0;
	if(WcsCmp(str,L"LANService") == 0)
		{
		servFlag = 0;
		}
	else if(WcsCmp(str,L"OutgoingGPRS") == 0)
		{
		servFlag  = 1;	
		}
	if(aType == EACCESS_SETMETRIC)
		{
		ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETMETRIC);					
		}	
	else if(aType == EACCESS_SETMTU)
		{
		ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETMTU);					
		}		
	else if(aType == EACCESS_SETFLAGS)
		{
		ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETFLAGS);					
		}
	else if(aType == EACCESS_SETPHYSADDR)
		{
		ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETPHYSADDR);					
		}	
	else if(aType == EACCESS_SETNETMASK)
		{
		ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETNETMASK);					
		}	
	else if(aType == EACCESS_SETBROADCAST)
		{
		ret = SetInterfaceDetails(aParam,servFlag,EACCESS_SETBROADCAST);					
		}		
	return ret;	

	}

void CSocketDesc::FindConnectionInfoL(TAccessPointRecord &aRecord,char *ptr)
	{
	//TAccessPointRecord tempRecord;
	CCommsDatabase* iapDatabase;
	CCommsDbTableView* view;
	TInt res;	
	TPtrC8 tptr((TText8*)ptr);
	TBuf<KCommsDbSvrMaxColumnNameLength> temp;
	res = CnvUtfConverter::ConvertToUnicodeFromUtf8(temp, tptr);
	if(res < KErrNone)
		{
		User::Leave(res);
		}
	else if(res > KErrNone)
		{
		User::Leave(KErrOverflow);
		}
	// This function can leave on insufficient memory
	OpenIapTableLC(&iapDatabase, &view);	
	res = view->GotoFirstRecord();
	while (res == KErrNone)
		{    	
		// On error continue with the next record	
		TRAP( res,ReadRecordFromIapTableL(view, aRecord));
		if (res == KErrNone)
			{   
			if(WcsCmp ((wchar_t*)aRecord.iName.PtrZ(),(wchar_t*)temp.PtrZ()) == 0)
				break; 	
			}    	
		res = view->GotoNextRecord();
		}
	CleanupStack::PopAndDestroy();// view
	CleanupStack::PopAndDestroy(iapDatabase);	
	return;
	}
#endif // __SYMBIAN_COMPILE_UNUSED__



TInt CSocketDesc::GetInterfaceInfo(TSoInetInterfaceInfo& aIfInfo, TInt aIapId )
	{
	 TPckgBuf<TSoInetInterfaceInfo> info;		
	TInt ret = KErrNone;
	ATOMICSOCKETOP( ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle )
	if (ret != KErrNone)
		{
		return KErrGeneral;
		}    	
	ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info), ret = KErrBadHandle )
	while(ret == KErrNone)
		{			
		if(info().iName != _L(""))
            {   			
            TPckgBuf<TSoInetIfQuery> optifquery;
            optifquery().iName = info().iName;
			ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, optifquery), ret = KErrBadHandle )
            if( ret  == KErrNone)
                {
                if(optifquery().iZone[1] == aIapId && info().iAddress.Address() != NULL)
                	{
                    aIfInfo = info();
                	return KErrNone;
                	}
                }
            }
			ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info), ret = KErrBadHandle )
        }
    return KErrNotFound;
	}
TInt CSocketDesc :: SetInterfaceDetails( void *aParam ,TInt /*aFlag*/, TInt aType, TInt aIapId )
	{
	TSoInet6InterfaceInfo ifInfo; 
	TInt ret = KErrNone;
	if((ret = GetInterfaceInfo(ifInfo,aIapId)) != KErrNone)
		{
		return ret;
		}
    ifreq *ifr = (ifreq *)aParam;
	switch(aType)
		{				
		case  EACCESS_SETMETRIC:
			if(ifInfo.iState == EIfUp)										 
				{
				ifInfo.iSpeedMetric =  ifr->ifr_metric;
				}
			break;

		case  EACCESS_SETMTU:										 
			if(ifInfo.iState == EIfUp)
				{
				ifInfo.iMtu = ifr->ifr_mtu ;		
				}		
			break;

		case  EACCESS_SETPHYSADDR :										
			// Currently no imeplentation is given as KIfHasHardwareAddr is always 
			// set to 0 for wlan and GPRS
			if(ifInfo.iFeatures&KIfHasHardwareAddr)
				{
				return KErrNotSupported;
				}
			break;							
		case EACCESS_SETDNSSUFFIX:
			{
			if_dns_suffixes * dns_suffix = static_cast<if_dns_suffixes *>(aParam);
			char **suffixes = dns_suffix->suffixes;
			TSoInetInterfaceInfoExtnDnsSuffix interfaceInfo;
			(TSoInetInterfaceInfo &)interfaceInfo = ifInfo;
			interfaceInfo.iDomainSuffix.DeleteAll();
            TPckgBuf<TSoInetInterfaceInfoExtnDnsSuffix> configInfo(interfaceInfo);

			ATOMICSOCKETOP(ret = iSocket.SetOpt(KSoInetConfigInterface,KSolInetIfCtrl,configInfo), ret = KErrBadHandle)

			for(int i = 0; suffixes[i]; i++)  //check the number of suffixes that can be configured
				{
				TPtrC8 suffix((const unsigned char *)suffixes[i]); 
				/*ret = configInfo().iDomainSuffix.Copy(suffix);
				if(ret != KErrNone)
				    {
                    return ret;
				    }*/
				ret = CnvUtfConverter::ConvertToUnicodeFromUtf8(configInfo().iDomainSuffix.iSuffixName,suffix);
				configInfo().iDomainSuffix.iDomainSuffixFunction = EInetAddSuffix;
               ATOMICSOCKETOP( ret = iSocket.SetOpt(KSoInetConfigInterface,KSolInetIfCtrl,configInfo), ret = KErrBadHandle)
                if(ret != KErrNone)
                    {
                    return ret;
                    }
				
				}
			return ret;
			}
		case EACCESS_SETNAMESERVERS:
			{
			if_name_servers *name_server = static_cast<if_name_servers*>(aParam);
			if((ret = ConvertSockToTInetAddr(&name_server->nameserver1,ifInfo.iNameSer1)) != KErrNone)
				{
				return ret;
				}
			if((ret = ConvertSockToTInetAddr(&name_server->nameserver2,ifInfo.iNameSer2)) != KErrNone)
				{
				return ret;
				}
			break;
			}

		default:
			return KErrArgument;					 
		}
	TPckgBuf<TSoInet6InterfaceInfo> pkgIfInfo(ifInfo);
	ATOMICSOCKETOP(ret = iSocket.SetOpt(KSoInetConfigInterface, KSolInetIfCtrl,pkgIfInfo), ret = KErrBadHandle)
	return ret;
	}

//This function frees the memory allocated by SIOCGETDNSSUFFIX ioctl
void CSocketDesc::FreeDNSSuffixes(char ** suffixes)
    {
    for(int i = 0; suffixes[i]; i++)
        {
        delete[] suffixes[i];
        }
    delete[] suffixes;
    }

TInt CSocketDesc::GetInterfaceDetails( void *aParam ,TInt /*aFlag*/, TInt aType, TInt aIapId )
	{

	ifreq *ifr = (ifreq *)aParam;
	*(ifr->ifr_addr.sa_data) = '\0';
    TInt ret = 0;

    TSoInetInterfaceInfo ifInfo; 

	if((ret = GetInterfaceInfo(ifInfo,aIapId)) != KErrNone)
		{
		return ret;
		}

	switch(aType)
		{

		case  EACTIVE_GETIP :
			if(ifInfo.iState == EIfUp)
				{
				ret = ConvertTInetToSockAddr(ifInfo.iAddress,&ifr->ifr_addr);
				return ret;
				}
			break;
		case  EACCESS_GETMETRIC:
			if(ifInfo.iState == EIfUp)
				{
				ifr->ifr_metric = ifInfo.iSpeedMetric;
				return KErrNone;
				}
			break;
		case  EACCESS_GETMTU:
			if(ifInfo.iState == EIfUp)
				{
				ifr->ifr_mtu = ifInfo.iMtu;
				return KErrNone;
				}
			break;	
		case  EACCESS_GETNETMASK :
			// Presently netmask address is NULL
			if(ifInfo.iState == EIfUp)
				{
				ret = ConvertTInetToSockAddr(ifInfo.iNetMask,&ifr->ifr_addr);
				return ret;
				}
			break;	
		case  EACCESS_GETBROADCAST :
			// Presently Breaodcast address is NULL
			if(ifInfo.iState == EIfUp)
				{
				ret = ConvertTInetToSockAddr(ifInfo.iBrdAddr,&ifr->ifr_broadaddr);
				return ret;
				}
			break;
		case EACCESS_GETDNSSUFFIX:
		    {

		    TInetSuffix data;
		    TPckgBuf<TInetSuffix> opt(data);
		    // Set the option to start enumeration of domain suffix on the active interface
			TInt err = KErrNone;
		    ATOMICSOCKETOP( err = iSocket.SetOpt(KSoInetEnumDomainSuffix, KSolInetIfCtrl), err = KErrBadHandle) 
		    if(err != KErrNone) 
		        {
		        return err;
		        }
		    struct if_dns_suffixes * dns_suffix = static_cast<if_dns_suffixes *>(aParam);
		    RPointerArray<char> suffixArray;
			ATOMICSOCKETOP (err = iSocket.GetOpt(KSoInetNextDomainSuffix, KSolInetIfCtrl, opt),err = KErrBadHandle)
		    while(err == KErrNone)
		        {
                char *suffix = new char[opt().iSuffixName.Length()+1];
                if((ret = suffixArray.Append(suffix)) != KErrNone)
                    {
                    suffixArray.ResetAndDestroy();
                    return ret;
                    }
                TPtr8 ptr((unsigned char *)suffix,opt().iSuffixName.Length()+1);
                ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(ptr,opt().iSuffixName);
                //ptr.Copy(opt().iSuffixName);
                if(ret != KErrNone)
                    {
                    suffixArray.ResetAndDestroy();
                    return ret;
                    }
                ptr.ZeroTerminate();
				ATOMICSOCKETOP (err = iSocket.GetOpt(KSoInetNextDomainSuffix, KSolInetIfCtrl, opt),err = KErrBadHandle)
		    	}

		    dns_suffix->suffixes = new char*[suffixArray.Count() + 1];
		    for(int i = 0 ; i< suffixArray.Count(); i++)
		    	{
                dns_suffix->suffixes[i] = suffixArray[i];
		    	}
            dns_suffix->suffixes[suffixArray.Count()] = NULL;
            suffixArray.Close();
            return KErrNone;

		}
			
		case EACCESS_GETNAMESERVERS:
			{
			if_name_servers *name_server = static_cast<if_name_servers*>(aParam);
			if((ret = ConvertTInetToSockAddr(ifInfo.iNameSer1, &name_server->nameserver1)) != KErrNone)
				{
				return ret;
				}
			if((ret = ConvertTInetToSockAddr(ifInfo.iNameSer2, &name_server->nameserver2)) != KErrNone)
				{
				return ret;
				}
			return KErrNone;

			}

		case  EACCESS_GETPHYSADDR :
			ifr->ifr_phys = 0;
			// Currently no imeplentation is given as KIfHasHardwareAddr is always 
			// set to 0 for wlan and GPRS
			if(ifInfo.iFeatures&KIfHasHardwareAddr)
				{
				//nada.
				}
			return KErrNotSupported;

		case EACCESS_GETDEFGATEWAY:
			if(ifInfo.iState == EIfUp)
				{
				ret = ConvertTInetToSockAddr(ifInfo.iDefGate,&ifr->ifr_defgatewayaddr);
				return ret;
				}
			break;


		case  EACCESS_GETFLAGS :
			ifr->ifr_flags = 0;
			ifr->ifr_flagshigh=0;
			// Interface UP
			if(ifInfo.iState == EIfUp)
				{
				ifr->ifr_flags |= IFF_UP; 
				ifr->ifr_flags |= IFF_DRV_RUNNING;
				}
			// Loopback
			if(ifInfo.iFeatures&KIfIsLoopback)
				{
				ifr->ifr_flags |= IFF_LOOPBACK;
				}										            													           

			// point to point support
			if(ifInfo.iFeatures&KIfIsPointToPoint) 
				{
				ifr->ifr_flags |= IFF_POINTOPOINT;  
				}

			// Broadcast
			if(ifInfo.iFeatures&KIfCanBroadcast)
				{
				ifr->ifr_flags |= IFF_BROADCAST;
				}      

			// Multicast
			if(ifInfo.iFeatures&KIfCanMulticast)
				{
				ifr->ifr_flagshigh |= ((IFF_MULTICAST & 0xff00) >> 8);
				}
			return KErrNone;

		default:
			return KErrArgument;                   
		}


	return KErrNotFound;

	}

TInt CSocketDesc::Poll(TPollMode aMode,TBool& aReadyStatus,TInt& aErrno)
	{
	TInt ret = maybe_reopen_socket();
    if (ret != KErrNone)
        {
        return ret;
        }

    TInt status;
    ATOMICSOCKETOP(ret = iSocket.GetOpt(KSOSelectPoll, KSOLSocket, status), ret = KErrBadHandle)
    if (ret == KErrNone)
		{
    	aReadyStatus = status & aMode;	
		}
    
    return MapError(ret, aErrno);
	}

/* The synchronous - non-blocking Poll */
TInt CSocketDesc::Poll(TUint aEvents)
	{

    TInt err = maybe_reopen_socket();
	if (err != KErrNone)
	    return err;
		
	return CSockDescBase::Poll(aEvents);
	}


/* Cancel an outstanding notification request */
void CSocketDesc::CancelNotify()
	{
	CSockDescBase::CancelNotify();
	}

TAccessPointRecord::TAccessPointRecord()
:iId(0), 
iName(0),
iDialogPref(ECommDbDialogPrefDoNotPrompt),
iDirection(ECommDbConnectionDirectionUnknown), 
iService(0),
iServiceType(0), // Text value
iBearer(0),
iBearerType(0),	// Text value
iNetwork(0),
iNetworkWeighting(0),
iLocation(0)
		{
		}

inline TInt CSocketDesc::GetInterfaceList(void *aParam)
	{
	return GetInterface(aParam, EACCESS_POINT);
	}

TInt CSocketDesc::GetInterfaceIndexByName(void *aParam)
	{
	ifreq *ifrQuery = (ifreq*)aParam;	
	ifconf ifc;

	// Know how many interfaces
	ifc.ifc_len = 0;
	ifc.ifc_buf = NULL;
	TInt ret = GetInterface(&ifc, EACCESS_POINT);
	if (ret != KErrNone)
		{
		return ret;
		}

	// Allocate the memory to get the detail interface information
	ifc.ifc_buf = (caddr_t)Backend()->Alloc( ifc.ifc_len);
	if (ifc.ifc_buf == NULL)
		{
		return KErrNoMemory;
		}
	ret = GetInterface(&ifc, EACCESS_POINT);
	if (ret != KErrNone)
		{
		Backend()->Free(ifc.ifc_buf);
		return ret;
		}
	ifreq *ifr = ifc.ifc_req;
	TInt ifCount = ifc.ifc_len / sizeof(ifreq);
	TInt i = 0;

	// We wouldn't need this if we were using a StrNcmp below
	ifrQuery->ifr_name[IFNAMSIZ-1] = 0; // don't assume NULL terminated input
	// Search for the interface name
	for (; i < ifCount; i++, ifr++)
		{
		if ( StrCmp(ifrQuery->ifr_name, ifr->ifr_name) == 0)
			{
			ifrQuery->ifr_index = ifr->ifr_index;
			break;
			}
		}

	if (i == ifCount)
		{
		ret = KErrNotFound;
		}
	Backend()->Free(ifc.ifc_buf);
	return ret;
	}

inline TInt CSocketDesc::GetActiveInterfaceList(void *aParam)
	{
	return GetInterface(aParam, EACTIVE_CONNECTION);
	}

TInt CSocketDesc::GetInterface(void *aParam, TInt aType)
	{
	TInt ret = KErrNone;
	ifconf *ifc = (ifconf*)aParam;	
	TInt length = (ifc->ifc_len) / sizeof(ifreq);
	TInt count = 0;
	// If the length is zero, fill the number of interface information
	if ( length <= 0 || ifc->ifc_buf == NULL )
		{
		if (aType == EACCESS_POINT)
			{
			TRAP(ret, AccessPointCountL(count));
			}
		else if (aType == EACTIVE_CONNECTION)
			{
			ret = ActiveConnectionCount(count);
			}
		else
			{
			ret = KErrArgument;
			}

		if (ret == KErrNone)
		    {
            ifc->ifc_len = sizeof(ifreq) * count;
		    }
		return ret;
		}

	// length is not 0, read 'length' number of records
	CArrayFixFlat<TAccessPointRecord> *apArray;
	wchar_t *str;
	TInt apIndex;
	TInt result = KErrNone;
	ifreq *ifr = ifc->ifc_req;
	TInt ActiveSet = 0;

	// Fixed array of 'length'
	apArray = new CArrayFixFlat<TAccessPointRecord>(length);
	if (apArray == NULL)
		{
		return KErrNoMemory;
		}
	if (aType == EACCESS_POINT)
		{
		// On return length would contain the number of access points.
		TRAP(result, AccessPointListL(apArray, length));
		}
	else if (aType == EACTIVE_CONNECTION)
		{
		TRAP(ret, ret=ActiveConnectionListL(apArray, length));
		if( ret == KErrNone )
			{
			TRAP(ret,FindConnectionDetailsL(apArray, length));
			ActiveSet = 1;  	
			}
		}
	if (ret != KErrNone)
		{
		delete apArray;
		return ret;
		}
	for (apIndex = 0; apIndex < length; apIndex++,ifr++)
		{
		TAccessPointRecord& ref = (*apArray)[apIndex];
		ifr->ifr_name[IFNAMSIZ-1] = 0; // don't assume NULL terminated input
		TPtr8 ptr((TText8*)ifr->ifr_name, IFNAMSIZ);

		ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(ptr, ref.iName);
		if(ret == KErrNone)
			{
			if(ptr.Length() < ptr.MaxLength())
				{
				ptr.ZeroTerminate();
				} 
			else
				{
				return KErrOverflow;
				} 
			}
		else if (ret > KErrNone)
			{
			return KErrOverflow;
			} 
		else
			{
			return ret;
			}

		// Copy theinterface index
		ifr->ifr_index = ref.iId;
		if(ActiveSet == 1)
			{
			str = (wchar_t *)(ref.iServiceType.PtrZ() ); 
			TInt servFlag = 0;
			if(WcsCmp(str,L"LANService") == 0)
				{
				servFlag = 0;
				}
			else if(WcsCmp(str,L"OutgoingGPRS") == 0)
				{
				servFlag  = 1;	
				}
			GetInterfaceDetails(ifr,servFlag,EACTIVE_GETIP,ref.iId);
			}
		}
	ifc->ifc_len = sizeof(ifreq) * apIndex;
	delete apArray;	
	return KErrNone;
	}

TInt CSocketDesc::SetInterfaceByName(void *aParam)
	{
	ifreq *ifr = (ifreq *)aParam;
	if (!ifr)
		{
		return KErrArgument;
		}

	ifr->ifr_name[IFNAMSIZ-1] = 0; // don't assume NULL terminated input
	TPtrC8 ptr((TText8*)ifr->ifr_name);
	TInt ret = CnvUtfConverter::ConvertToUnicodeFromUtf8(iConnPref.iName,ptr);
	if(ret > KErrNone )
		{
		return KErrOverflow;
		}
	return ret; 
	}

inline TInt CSocketDesc::StartInterface(void *aParam)
	{
	return StartConnection(aParam);	
	}

inline TInt CSocketDesc::StartActiveInterface(void *aParam)
	{
	return StartSubConnection(aParam);	
	}

TInt CSocketDesc::StopInterface(void *)
	{
	if (iConnectionPtr != NULL)
		{
		StopConnection();
		return KErrNone;
		}
	else if (iSubConnectionPtr != NULL)
		{
		StopSubConnection();
		return KErrNone;
		}	
	return KErrNotFound;
	}

TInt CSocketDesc::OpenUsingPreference()
	{
	TInt ret = 0;	
    // Update when supporting INET6
    TInt addrfamily = (iAddrFamily == AF_INET6 ? KAfInet : iAddrFamily);	
	if (iConnectionPtr != NULL) // iConnection initialized
		{
		ret = iSocket.Open(*iSockServPtr,addrfamily,iStyle,iProtocol,iConnection);
		}
	else if (iSubConnectionPtr != NULL) // iSubConnection initialized
		{
		ret = iSocket.Open(*iSockServPtr,addrfamily,iStyle,iProtocol,iSubConnection);
		}
	else
	    {
	    RConnection& defConnection = Backend()->GetDefaultConnection();
	    //Now check if the default connection is intialized. This is given lesser 
	     //priority than the socket specific preferences checked above.
	     if(defConnection.SubSessionHandle() != 0)
	         {
	         ret = iSocket.Open(*iSockServPtr,addrfamily,iStyle,iProtocol,defConnection);	         
	         if (!ret)
	             {
	             Backend()->AddSocket(this);
	             }
	         }
	     else // No connection preference is set
	         {
	         ret = ECONNABORTED;
            }
        }
    
    if (ret == KErrNone)
        {
        __e32_atomic_store_rel32(&iSocketPtr, (unsigned long)&iSocket);
        }
    
    iConnectInProgress = EFalse;

    return ret;
    }

void CSocketDesc::TempClose()
    {
    TUint32 ret = __e32_atomic_ior_ord32((void *)&iCount,0x8000);
    if( ret >= 0x8000 )
        {
        // This indicates a TempClose has already been done from one of the threads
        return;
        }
    // loop and yeild till no more references are held to the iSocket
    while( iCount != 0x8000 )
        {
        // Yeild for 1 ms
        User::After(1000);
        }
    if (iSocket.SubSessionHandle() != 0)
        {
	    iSocketPtr = NULL;
        iSocket.CancelAll();    
        TRequestStatus status;
        iSocket.Shutdown(RSocket::EImmediate, status);
        User::WaitForRequest(status);
        iSocket.Close();
        }
    }

void CSocketDesc::AccessPointListL(CArrayFixFlat<TAccessPointRecord> *&aRecordPtr,
		TInt &aCount)
	{
	TAccessPointRecord tempRecord;
	CCommsDatabase* iapDatabase;
	CCommsDbTableView* view;

	// This function can leave on insufficient memory
	OpenIapTableLC(&iapDatabase, &view);
	TInt count = 0;
	TInt ret = view->GotoFirstRecord();
    while (ret == KErrNone && count < aCount)
		{
    	TRAP(ret, ReadRecordFromIapTableL(view, tempRecord));
    	if (ret == KErrNone)
			{
			aRecordPtr->AppendL(tempRecord);
			count++;
			}	
    	ret = view->GotoNextRecord();
		}
    
	CleanupStack::PopAndDestroy();// view
	CleanupStack::PopAndDestroy(iapDatabase);
	aCount = aRecordPtr->Count();
	}

void CSocketDesc::FindConnectionDetailsL(CArrayFixFlat<TAccessPointRecord> *&aRecordPtr,
		TInt &aCount)
	{
	TAccessPointRecord tempRecord;
	CCommsDatabase* iapDatabase;
	CCommsDbTableView* view;

	// This function can leave on insufficient memory
	OpenIapTableLC(&iapDatabase, &view);
	TInt count = 0;
	TInt ret = view->GotoFirstRecord();
    while (ret == KErrNone && count < aCount)
		{
    	TRAP(ret, ReadRecordFromIapTableL(view, tempRecord));
    	if (ret == KErrNone)
			{    		
			if((*aRecordPtr)[count].iId == tempRecord.iId )    			
				{    			    		
				(*aRecordPtr)[count].iServiceType = tempRecord.iServiceType;
				ret = view->GotoFirstRecord();
				count++;    		
				continue;
				}    		
    		ret = view->GotoNextRecord();
			}
		}
    
	CleanupStack::PopAndDestroy();// view
	CleanupStack::PopAndDestroy(iapDatabase);
	aCount = aRecordPtr->Count();
		}

void CSocketDesc::AccessPointCountL(TInt &aCount)
	{
	CCommsDatabase* iapDatabase;
	CCommsDbTableView* view;

	OpenIapTableLC(&iapDatabase, &view);
	aCount = 0;
	TInt ret = view->GotoFirstRecord();
	while(ret == KErrNone)
		{
		aCount++;
		ret = view->GotoNextRecord();
		}
	CleanupStack::PopAndDestroy();// view
	CleanupStack::PopAndDestroy(iapDatabase);
	}

void CSocketDesc::ReadRecordFromIapTableL(CCommsDbTableView* aView, TAccessPointRecord &aRecord)
	{
	aView->ReadUintL(TPtrC(COMMDB_ID), aRecord.iId);
	aView->ReadTextL(TPtrC(COMMDB_NAME), aRecord.iName); 
	aRecord.iDialogPref = ECommDbDialogPrefDoNotPrompt;
	aView->ReadUintL(TPtrC(IAP_SERVICE), aRecord.iService);
	aView->ReadTextL(TPtrC(IAP_SERVICE_TYPE), aRecord.iServiceType);
	aView->ReadUintL(TPtrC(IAP_BEARER), aRecord.iBearer);
	/*
	 * IAP_BEARER_TYPE is not a column of IAP table even though its 
	 * listed in header. So not trying to read it.
	 */
	aView->ReadUintL(TPtrC(IAP_NETWORK), aRecord.iNetwork);
	aView->ReadUintL(TPtrC(IAP_NETWORK_WEIGHTING), aRecord.iNetworkWeighting);
	aView->ReadUintL(TPtrC(IAP_LOCATION), aRecord.iLocation);
	}

void CSocketDesc::OpenIapTableLC(CCommsDatabase **aIapDatabase, CCommsDbTableView **aView)
	{
	// Get IAP names and ids from the database
	*aIapDatabase = CCommsDatabase::NewL(EDatabaseTypeIAP);
	CleanupStack::PushL(*aIapDatabase);

	(*aIapDatabase)->ShowHiddenRecords();

	// This is LC code, that means code has pushed, but not popped
	(*aView) = (*aIapDatabase)->OpenTableLC(TPtrC(IAP));
	}

inline TInt CSocketDesc::ActiveConnectionCount(TInt &aCount)
	{
	aCount = ((CFileTable*)iFids)->RConnectionCount();
	return KErrNone;
	}

TInt CSocketDesc::ActiveConnectionListL(CArrayFixFlat<TAccessPointRecord> *aRecordPtr, TInt &aLength)
	{
	TInt rcIndex;
	RConnection *rc;
	TAccessPointRecord tempRecord;

	for (rcIndex = 0;rcIndex < aLength; rcIndex++)
		{
		if  ( ((CFileTable*)iFids)->RConnectionAt(rcIndex, rc) != KErrNone )
			{
			break;
			}
		// Read index and name of the connection
		if  ( GetRConnectionDetails(rc, tempRecord) != KErrNone )
			{
			break;
			}
		aRecordPtr->AppendL(tempRecord);
		}
	aLength = aRecordPtr->Count();
	return KErrNone;
	}

TInt CSocketDesc::GetRConnectionDetails(RConnection *aRc, TAccessPointRecord &aApr)
	{
	_LIT(KName, "IAP\\Name");
	_LIT(KId, "IAP\\Id");

	TInt ret = aRc->GetDesSetting(KName, aApr.iName);
	if (ret == KErrNone)
		{
		ret = aRc->GetIntSetting(KId, aApr.iId);
		}
	
		return ret;
		}

TInt CSocketDesc::StartConnection(void * /* ptr */)
	{
	if (iConnectionPtr != NULL)
		{
		return KErrAlreadyExists;
		}
	TCommDbConnPref connPref;
	TInt ret = GetConnectionPreference(connPref);
	if (ret != KErrNone)
		{
		return ret;
		}
	ret = iConnection.Open(*iSockServPtr);
	if (ret != KErrNone)
		{
		return ret;
		}	
	ret = iConnection.Start(connPref);
	if (ret != KErrNone)
		{
		iConnection.Close();
		return ret;
		}
	iConnectionPtr = &iConnection;
	ret = ((CFileTable*)iFids)->AddRConnectionPtr(iConnectionPtr, iRConnectionIndex);
	if (ret != KErrNone)
		{
		iConnection.Close();
		iConnectionPtr = NULL;
		}
	return ret;
	}

TInt CSocketDesc::GetConnectionPreference(TCommDbConnPref &aCommPref)
	{
	if (iConnPref.iName.Length() == 0)
		{
		return KErrArgument;
		}
	
	TAccessPointRecord apr;	
	TInt ret;

	// Connection preference is set
		TRAP(ret, GetIapDetailsByNameL(iConnPref.iName, apr));

	if (ret == KErrNone)
		{
		aCommPref.SetIapId(apr.iId);
		aCommPref.SetNetId(apr.iNetwork);
		aCommPref.SetBearerSet(apr.iBearer);		
		aCommPref.SetDialogPreference((TCommDbDialogPref)apr.iDialogPref);
		aCommPref.SetDirection((TCommDbConnectionDirection)apr.iDirection);
		}
	return ret;	
	}

void CSocketDesc::GetIapDetailsByNameL(
		TBuf<KCommsDbSvrMaxColumnNameLength> aIapName, 
		TAccessPointRecord &aRecord)
	{
	TAccessPointRecord tempRecord;
	CCommsDatabase* iapDatabase;
	CCommsDbTableView* view;
	TInt ret = KErrNotFound;

	OpenIapTableLC(&iapDatabase, &view);
	ret = view->GotoFirstRecord();
	while (ret == KErrNone)
		{
		TRAP(ret, ReadRecordFromIapTableL(view, tempRecord));
		if (ret == KErrNone)
			{
			if (aIapName == tempRecord.iName)
				{
				aRecord = tempRecord;
				ret = KErrNone;
				break;
				}
			}    	
		ret = view->GotoNextRecord();
		}
	CleanupStack::PopAndDestroy();// view
	CleanupStack::PopAndDestroy(iapDatabase);

	if (ret != KErrNone)
		{
		User::Leave(KErrNotFound);
		}
	}

void CSocketDesc::StopConnection()
	{
	iConnection.Close();
	iConnectionPtr = NULL;
	((CFileTable*)iFids)->RemoveRConnectionPtrAt(iRConnectionIndex);
	iRConnectionIndex = -1;
	}

void CSocketDesc::StopSubConnection()
	{
	iSubConnection.Close();
	iSubConnectionPtr = NULL;
	}

TInt CSocketDesc::StartSubConnection(void *)
	{
	if (iSubConnectionPtr != NULL)
		{
		return KErrAlreadyExists;
		}

	TInt ret = KErrArgument;
	TInt rcIndex = 0;
	RConnection *rc;
	TAccessPointRecord record;	
	do
		{
		if (((CFileTable*)iFids)->RConnectionAt(rcIndex, rc) != KErrNone)
			{
			break;
			}

		// Read index and name of the connection
		GetRConnectionDetails(rc, record);
		if (record.iName == iConnPref.iName)
			{
			ret = KErrNone; // RConnection found
			break;
			}
		rcIndex++;	
		}
	while (ETrue); //Loop over all active connections

	if (ret == KErrNone)
		{
		ret = iSubConnection.Open(*iSockServPtr, RSubConnection::EAttachToDefault, *rc);
		if (ret == KErrNone)
			{
			iSubConnectionPtr = &iSubConnection;
			}
		}

	return ret;
	}

inline void CSocketDesc::SetFids(void *aFids)
	{
	iFids = aFids;
	}

//Add an entry in the interface routing table	
TInt CSocketDesc::RouteRequest(TInt aReq, void *aParam)
	{
	struct rtentry* rt=reinterpret_cast<struct rtentry*>(aParam);

	if (!rt)
		{
		return KErrArgument;	
		}

	TInt ret;
	TPckgBuf<TSoInetRouteInfo>iroute;	
	iroute().iType=ERtNormal;
	iroute().iState=ERtReady; 
	iroute().iMetric=rt->rt_metric;
	if (rt->rt_dev)
		{
		TPckgBuf<TSoInetInterfaceInfo> iface;		
		TFileName name;
		name.Copy(TPtrC8((TText8*)rt->rt_dev));

		if((ret=GetInterfaceByName(name, iface)) != KErrNone)
			return ret;

		Copy(iroute().iIfAddr, iface().iAddress);
		ConvertRtEntry(iroute(), rt);

		//add the entry
		ATOMICSOCKETOP( ret = iSocket.SetOpt(aReq, KSolInetRtCtrl, iroute),return KErrBadHandle )
		return ret;
		}

	return KErrUnknown;				
	}


TInt CSocketDesc::Copy(TInetAddr& aDest, TInetAddr& aSrc)
	{
	if (aSrc.IsV4Mapped() || aSrc.IsV4Compat())
		{
		aSrc.ConvertToV4();
		}

	aDest.SetAddress(aSrc.Address());
	aDest.SetFamily(aSrc.Family());
	aDest.SetPort(aSrc.Port());

	return KErrNone;
	}

TInt CSocketDesc::ConvertSockAddr(TInetAddr& aInetAddr, struct sockaddr_in *aSockAddr)
	{
	if (aSockAddr == NULL)
		{
		return KErrArgument;
		}

		//convert the address and port from network to host byte order...
		aInetAddr.SetAddress(ByteOrder::Swap32(aSockAddr->sin_addr.s_addr));
		aInetAddr.SetFamily(aSockAddr->sin_family);
		aInetAddr.SetPort(ByteOrder::Swap16(aSockAddr->sin_port));
	return KErrNone;	
	}

TInt CSocketDesc::ConvertRtEntry(TSoInetRouteInfo& aRouteInfo, struct rtentry *aRouteEntry)
	{
	if(aRouteEntry == NULL)	
		{
		return KErrArgument;
		}

		ConvertSockAddr(aRouteInfo.iDstAddr, (struct sockaddr_in *)&aRouteEntry->rt_dst);
		ConvertSockAddr(aRouteInfo.iNetMask, (struct sockaddr_in *)&aRouteEntry->rt_genmask);
		ConvertSockAddr(aRouteInfo.iGateway, (struct sockaddr_in *)&aRouteEntry->rt_gateway);			
	return KErrNone;	
	}

TInt CSocketDesc::GetInterfaceByName(const TDesC& aIfName, TPckgBuf<TSoInetInterfaceInfo>& aIface)
	{
	TInt ret = KErrNone;
	ATOMICSOCKETOP(ret = iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl), ret = KErrBadHandle)
	if (ret != KErrNone)
		{
		return ret;
		}
	TPckgBuf<TSoInetInterfaceInfo> iface;
	ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, iface), ret = KErrBadHandle)
	while(ret == KErrNone)
		{
		if (!iface().iAddress.IsUnspecified() && iface().iName.CompareF(aIfName) == 0)
			{
			aIface = iface;
			return ret;    	        
			}
		ATOMICSOCKETOP( ret = iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, iface), ret = KErrBadHandle )
		}   	
	return KErrUnknown;	
	}

TInt CSocketDesc::GetInterfaceHWAddress(void *aParam)
	{
	ifreq *ifr = reinterpret_cast<ifreq *>(aParam);

	if (!ifr)
		{
		return KErrArgument;	
		}

	if (ifr->ifr_name[0] != '\0')
		{
        TPckgBuf<TSoInetInterfaceInfo> iface;
        TFileName name;
        ifr->ifr_name[IFNAMSIZ-1] = 0; // don't assume NULL terminated input
        name.Copy(TPtrC8((TText8*)ifr->ifr_name));
    
        TInt ret = GetInterfaceByName(name, iface); 		
        if (ret != KErrNone)
            return ret;
    
        if (iface().iHwAddr.Length() > sizeof(SSockAddr))		
            {
            Mem::Copy(&(ifr->ifr_hwaddr.sa_data[0]),&(iface().iHwAddr[sizeof(SSockAddr)]), 6);
            ifr->ifr_hwaddr.sa_family = (TUint16)iface().iHwAddr.Family();
            ifr->ifr_hwaddr.sa_port = ByteOrder::Swap16(iface().iHwAddr.Port());				
            return ret;
            }
		}

	return KErrUnknown;
	}

//This function retrieves the Currently active IAP ID using the RSocket Query.
//First get the interface index of the active connection using KSoInterfaceIndex
//Then with the help of the interface index, fetch the TSoInetIfQuery, under which iZone
//will contain the snap id. User is supposed to call if_indextoname() api to get the IAP name
//from the ID retured with this Ioctl implementation.
TInt CSocketDesc::GetActiveInterface( void *aParam)
    {
    TInt ifindex = -1;
    TInt ret = KErrNone;
    ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInterfaceIndex, KSolInetIp , ifindex), ret = KErrBadHandle)
    if(ret!=KErrNone)
        {
        return ret;
        }   
    TPckgBuf<TSoInetIfQuery> opt;
    opt().iIndex = ifindex;
    ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInetIfQueryByIndex, KSolInetIfQuery, opt), ret = KErrBadHandle)
    if(ret!=KErrNone)
        {
        return ret;
        }
    ifreq *ifr = (ifreq * )aParam;
    ifr->ifr_index  = opt().iZone[1]; //IAP_ID
    return KErrNone;
    }


TInt CSocketDesc::GetActiveInterfaceIAPIdByName(const char *aIapName,TInt& aIapId)
    {

    TInt rcIndex = 0;
    RConnection *rc;
    TAccessPointRecord tempRecord;
    char iapName[IFNAMSIZ];
    TInt ret = KErrNotFound;
//    ifreq * ifr = static_cast<ifreq *> (aParam); //may not work, will have to reinterper_cast

    while(((CFileTable*)iFids)->RConnectionAt(rcIndex++, rc) == KErrNone)
        {
        if( GetRConnectionDetails(rc, tempRecord) != KErrNone )
            {
            continue;
            }
        TPtr8 ptr((TText8*)iapName, IFNAMSIZ-1);  

        ret = CnvUtfConverter::ConvertFromUnicodeToUtf8(ptr, tempRecord.iName);
        if(ret == KErrNone)
            {
           ptr.ZeroTerminate();
            if(StrCmp(iapName, aIapName) == 0)
                {
                aIapId = tempRecord.iId;
                return KErrNone; 
                }
            }
        }
    return ret;  //is it okay? ret contains rite val?
    }
//converts Symbian Inetaddres structure to posix sockaddr structure
TInt CSocketDesc::ConvertTInetToSockAddr(const TInetAddr& aInetAddr, sockaddr * aSockAddr )
    {
    TUSockAddr addr(aInetAddr); 
    unsigned long len = sizeof(sockaddr);
    addr.Get(aSockAddr,&len);
    return addr.iError;
    }

//converts posix sockaddr structure to Symbian Inetaddres structure 
TInt CSocketDesc::ConvertSockToTInetAddr(const sockaddr * aSockAddr, TInetAddr& aInetAddr)
    {
    unsigned int len = sizeof(sockaddr);
    TUSockAddr addr(aSockAddr,len);  
    aInetAddr =  addr;
    return addr.iError;
    }

//Gets the Iap id by IAP name and using iap id gets the interface details
TInt CSocketDesc::GetInterfaceAttributes(void *aParam, int aFlag)
    {
    ifreq * ifr = static_cast<ifreq *> (aParam); //may not work, will have to reinterper_cast
    TInt ret = KErrGeneral, iapId;
    ret = GetActiveInterfaceIAPIdByName(ifr->ifr_name,iapId);
    if(ret == KErrNone)
        {
        ret = GetInterfaceDetails( ifr ,0, aFlag, iapId);  //what to do with return value
        }
    return ret;
        
    }

//Gets the Iap id by IAP name and using iap id sets the interface details
TInt CSocketDesc::SetInterfaceAttributes(void *aParam, int aFlag)
    {
    ifreq * ifr = static_cast<ifreq *> (aParam); //access of only if_name guaranteed to work.
    TInt ret = KErrGeneral, iapId;
    ret = GetActiveInterfaceIAPIdByName(ifr->ifr_name,iapId);
    if(ret == KErrNone)
        {
        ret = SetInterfaceDetails( aParam ,0, aFlag, iapId);  //what to do with return value
        }
    return ret;
    }

//Enumerates the routes configured on the system	
TInt CSocketDesc::EnumerateRoutes(void *aParam)
    {
    TInt ret = KErrNone;
    rtconf *rtc = (rtconf*)aParam;
    TInt routeCount = (rtc->rt_len) /sizeof (route_entry);
    route_entry *rtentry = rtc->rtc_rtcu.rtcu_entry;
    ATOMICSOCKETOP(ret =  iSocket.SetOpt(KSoInetEnumRoutes, KSolInetRtCtrl),ret = KErrBadHandle)
    if(ret != KErrNone )
        {
        return ret;
        }
    //If the length is zero, we fill the number of routes available information
    TInt count = 0;
    TPckgBuf<TSoInetRouteInfo> route;
    if(routeCount <=0 || rtc->rtc_buf ==NULL)
        {
		ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInetNextRoute, KSolInetRtCtrl, route), ret = KErrBadHandle)
        while(ret == KErrNone)
        	{
        	count++;
			ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInetNextRoute, KSolInetRtCtrl, route), ret = KErrBadHandle)
        	}
        rtc->rt_len = count * sizeof(route_entry) ;
        return KErrNone;
        }
    for(TInt i=0; i<routeCount ; i++) 
    	{
		ATOMICSOCKETOP(ret = iSocket.GetOpt(KSoInetNextRoute, KSolInetRtCtrl, route),ret = KErrBadHandle)
    	if(ret != KErrNone)
    		{
    		break;
    		}	
    	ConvertTInetToSockAddr(route().iDstAddr, &rtentry[i].dst_addr);
    	ConvertTInetToSockAddr(route().iIfAddr, &rtentry[i].ifaddr);
    	ConvertTInetToSockAddr(route().iGateway, &rtentry[i].gateway_addr);
    	ConvertTInetToSockAddr(route().iNetMask, &rtentry[i].dst_netmask);
    	TInt state = route().iState;
    	TInt type = route().iType;
    	rtentry[i].rt_metric = route().iMetric;
    	rtentry[i].rt_flags.state = state;
    	rtentry[i].rt_flags.type = type;

    	}

    return KErrNone;    
    }

//Sets the nameserver of an interface
TInt CSocketDesc::SetNameServer(void *aParam, int aFlag)
    {
    if_name_servers * dns_server = static_cast<if_name_servers *> (aParam); //access of only if_name guaranteed to work.
    TInt iapId;
    TInt ret = GetActiveInterfaceIAPIdByName(dns_server->if_name, iapId);
    if(ret == KErrNone)
        {
        ret = SetInterfaceDetails( aParam ,0, aFlag, iapId);  //what to do with return value
        }
    return ret;
    }

//Gets the nameserver of an interface
TInt CSocketDesc::GetNameServer(void *aParam, int aFlag)
    {
    if_name_servers * dns_server = static_cast<if_name_servers *> (aParam); //access of only if_name guaranteed to work.
    TInt iapId;
    TInt ret = GetActiveInterfaceIAPIdByName(dns_server->if_name, iapId);
    if(ret == KErrNone)
        {
        ret = GetInterfaceDetails( dns_server ,0, aFlag, iapId);  //what to do with return value
        }
    return ret;     
    }
