genericopenlibs/openenvcore/backend/src/syscall/handlenms.cpp
changeset 0 e4d67989cc36
child 44 97b0fb8a2cc2
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 #include "sysreent.h"
       
    22 #include <sys/socket.h>
       
    23 #include <stdapis/netinet/in.h>
       
    24 #include <es_sock.h>
       
    25 #include <utf.h>
       
    26 
       
    27 #include "sysif.h"
       
    28 #include "fdesc.h"
       
    29 #include "lposix.h"
       
    30 
       
    31 #include "netdb_r.h"
       
    32 
       
    33 extern "C" {
       
    34 
       
    35 EXPORT_C int _socket_r (int *aErrno, int family, int style, int protocol)
       
    36 	{
       
    37 	return Backend()->socket(family, style, protocol, *aErrno);
       
    38 	}
       
    39 
       
    40 
       
    41 EXPORT_C int _recvfrom_r (int *aErrno, int fd, char *buf, size_t nbyte, int flags, struct sockaddr* from, size_t* fromsize)
       
    42 	{
       
    43 	return Backend()->recvfrom(fd, buf, nbyte, flags, from, (unsigned long*)fromsize, *aErrno);
       
    44 	}
       
    45 
       
    46 EXPORT_C int _sendto_r (int *aErrno, int fd, const char *buf, size_t nbyte, int flags, struct sockaddr* to, size_t tosize)
       
    47 	{
       
    48 	return Backend()->sendto(fd, buf, nbyte, flags, to, tosize, *aErrno);
       
    49 	}
       
    50 
       
    51 
       
    52 EXPORT_C int _shutdown_r (int *aErrno, int fd, int how)
       
    53 	{
       
    54 	return Backend()->shutdown(fd, how, *aErrno);
       
    55 	}
       
    56 
       
    57 EXPORT_C int _listen_r (int *aErrno, int fd, int n)
       
    58 	{
       
    59 	return Backend()->listen(fd, n, *aErrno);
       
    60 	}
       
    61 
       
    62 EXPORT_C int _accept_r (int *aErrno, int fd, struct sockaddr *addr, size_t *size)
       
    63 	{
       
    64 	int newfd = Backend()->accept(fd, addr, size, *aErrno);
       
    65 	if (newfd>=0 && (addr != NULL) && (size != NULL))
       
    66 		Backend()->sockname(newfd, addr, (unsigned long*)size, 1, *aErrno);	// getpeername
       
    67 	return newfd;
       
    68 	}
       
    69 
       
    70 EXPORT_C int _bind_r (int *aErrno, int fd,const struct sockaddr *addr, size_t size)
       
    71 	{
       
    72 	return Backend()->bind(fd, addr, size, *aErrno);
       
    73 	}
       
    74 
       
    75 
       
    76 EXPORT_C int _connect_r (int *aErrno, int fd, const struct sockaddr *addr, size_t size)
       
    77 	{
       
    78 	return Backend()->connect(fd, addr, size, *aErrno);
       
    79 	}
       
    80 
       
    81 EXPORT_C int _getsockname_r (int *aErrno, int fd, struct sockaddr *addr, size_t* size)
       
    82 	{
       
    83 	if (size == 0)
       
    84 		{
       
    85 		*aErrno = EINVAL;
       
    86 		return -1;
       
    87 		}
       
    88 
       
    89 	return Backend()->sockname(fd, addr, (unsigned long*)size, 0, *aErrno);
       
    90 	}
       
    91 
       
    92 EXPORT_C int _getpeername_r (int *aErrno, int fd, struct sockaddr *addr, size_t* size)
       
    93 	{
       
    94 	if (size == 0)
       
    95 		{
       
    96 		*aErrno = EINVAL;
       
    97 		return -1;
       
    98 		}
       
    99 	return Backend()->sockname(fd, addr, (unsigned long*)size, 1, *aErrno);
       
   100 	}
       
   101 
       
   102 EXPORT_C int _getsockopt_r (int *aErrno, int fd, int level, int opt, void* buf, size_t* len) 
       
   103 	{
       
   104 	if (len == 0)
       
   105 		{
       
   106 		*aErrno = EFAULT;
       
   107 		return -1;
       
   108 		}
       
   109 	return Backend()->getsockopt(fd, level, opt, buf, (unsigned long*)len, *aErrno);
       
   110 	}
       
   111 
       
   112 EXPORT_C int _setsockopt_r (int *aErrno, int fd, int level, int opt, void* buf, size_t len) 
       
   113 	{
       
   114 	return Backend()->setsockopt(fd, level, opt, buf, len, *aErrno);
       
   115 	}
       
   116 
       
   117 LOCAL_C inline TInt SockServConnect(RSocketServ& aSs)
       
   118 	{
       
   119 	TInt err = aSs.Connect(TUint(-1)); // allow arbit number of requests
       
   120 	if (err == KErrNone)
       
   121 		{
       
   122 		err = aSs.ShareAuto();
       
   123 		}
       
   124 	return err;
       
   125 	}
       
   126 
       
   127 EXPORT_C int _gethostname_r (int *aErrno, char *name, size_t size)
       
   128 	{
       
   129 	TInt err = KErrNone;
       
   130 	if(size <= 0)
       
   131         {
       
   132         return MapError(EINVAL, *aErrno);
       
   133         }
       
   134 	RSocketServ& ss = Backend()->SockServSession();
       
   135 	// connect to the Socket Server if necessary
       
   136 	if (ss.Handle() == 0)
       
   137 		{
       
   138 		err = SockServConnect(ss);
       
   139 		if (err != KErrNone)
       
   140 			{
       
   141 			return MapError(err, *aErrno);
       
   142 			}
       
   143 		}
       
   144 	
       
   145 	RHostResolver hr;
       
   146 	/* Get the default RConnection instance and use it if configured. 
       
   147 	   NOTE: This RConnection, if configured, would be created using the
       
   148 	   socket server on backend. The same server has to be used here */
       
   149 	RConnection defConnection = Backend()->GetDefaultConnection();
       
   150 	if(defConnection.SubSessionHandle() != 0)
       
   151 	    {
       
   152 	    err = hr.Open(ss, AF_INET, IPPROTO_UDP,defConnection);
       
   153 	    }
       
   154 	else
       
   155 	    {
       
   156 		err = hr.Open(ss, AF_INET, IPPROTO_UDP);
       
   157 	    }
       
   158 	
       
   159 	if (err == KErrNone)
       
   160 		{
       
   161 		TBuf<128> hostname;
       
   162 		err = hr.GetHostName(hostname);
       
   163 		if (err == KErrNone)
       
   164 			{
       
   165 				TPtr8 ret((TText8*)name, size-1);
       
   166 				if(CnvUtfConverter::ConvertFromUnicodeToUtf8(ret,hostname) == 0)
       
   167 				{
       
   168 				name[ret.Size()] = '\0';
       
   169 				}
       
   170 		    	else
       
   171 				{
       
   172 				err = ENAMETOOLONG;
       
   173 				}
       
   174 				
       
   175 			}
       
   176 		}
       
   177 		hr.Close();
       
   178 	return MapError(err, *aErrno);
       
   179 	}
       
   180 
       
   181 EXPORT_C int _getprotobyname_r(int* aErrno, const char* name, TProtocolDesc* pProtoInf)
       
   182 	{
       
   183 	TInt err = KErrNone;
       
   184 	RSocketServ& ss = Backend()->SockServSession();
       
   185 	// connect to the Socket Server if necessary
       
   186 	if (ss.Handle() == 0)
       
   187 		{
       
   188 		err = SockServConnect(ss);
       
   189 		if (err != KErrNone)
       
   190 			{
       
   191 			return MapError(err, *aErrno);
       
   192 			}
       
   193 		}
       
   194 		
       
   195 	TBuf<128> buf;
       
   196 	TPtrC8 bufPtr((TText8*)name);
       
   197 	buf.Copy(bufPtr);
       
   198 	
       
   199 	err = ss.FindProtocol(buf, *pProtoInf);
       
   200 	return MapError(err, *aErrno);
       
   201 	}
       
   202 
       
   203 EXPORT_C int _getprotobynumber_r(int *aErrno, int proto, TProtocolDesc* pProtoInf)
       
   204 	{
       
   205 	TInt err = KErrNone;
       
   206 	RSocketServ& ss = Backend()->SockServSession();
       
   207 	// connect to the Socket Server if necessary
       
   208 	if (ss.Handle() == 0)
       
   209 		{
       
   210 		err = SockServConnect(ss);
       
   211 		if (err != KErrNone)
       
   212 			{
       
   213 			return MapError(err, *aErrno);
       
   214 			}
       
   215 		}
       
   216 		
       
   217 	TUint count;
       
   218 	err = ss.NumProtocols(count);
       
   219 	if (err == KErrNone)
       
   220 		{
       
   221 		TInt idx = 1;
       
   222 		for (; idx <= count; ++idx)
       
   223 			{
       
   224 			err = ss.GetProtocolInfo(idx, *pProtoInf);
       
   225 			if (err != KErrNone || pProtoInf->iProtocol == proto)
       
   226 				{
       
   227 				break;
       
   228 				}
       
   229 			}
       
   230 		
       
   231 		if (idx > count)
       
   232 			{
       
   233 			// no protocol matched input
       
   234 			return -1;
       
   235 			}
       
   236 		}
       
   237 	return MapError(err, *aErrno);
       
   238 	}
       
   239 
       
   240 
       
   241 struct hostent_buf
       
   242 	{
       
   243 	struct hostent iHostent;
       
   244 	struct sockaddr iAddr;
       
   245 	char* iPtrs[2];
       
   246 	char iName[1];	// and following bytes
       
   247 	};
       
   248 
       
   249 struct hostent* mapNameRecord(struct _reent* rp, TNameRecord& aRecord, int length, int format)
       
   250 	{
       
   251 	Backend()->Free(rp->_netdb);
       
   252 	HBufC8 * name;
       
   253 	TInt errNum;
       
   254 	if(ConvertUnicodeToUtf8(aRecord.iName,name,errNum) == -1)
       
   255 		{
       
   256 		rp->_errno = EINVAL;
       
   257 		return 0;
       
   258 		}
       
   259 
       
   260 	// Switch to the backend heap
       
   261 	RHeap* oldHeap = User::SwitchHeap(Backend()->Heap());
       
   262 	struct hostent_buf* hbp = (struct hostent_buf*)Backend()->Alloc(sizeof(struct hostent_buf)+name->Size()+1);
       
   263 	// Revert to the default heap
       
   264 	User::SwitchHeap(oldHeap);
       
   265 
       
   266 	rp->_netdb = hbp;
       
   267 	if (hbp == 0)
       
   268 		{
       
   269 		delete name;
       
   270 		rp->_errno = ENOMEM;
       
   271 		return 0;
       
   272 		}
       
   273 	hbp->iHostent.h_name = &hbp->iName[0];		// one name
       
   274 	hbp->iHostent.h_aliases = &hbp->iPtrs[1];	// no aliases
       
   275 	hbp->iHostent.h_addrtype = format;
       
   276 	hbp->iHostent.h_length = length;
       
   277 	hbp->iHostent.h_addr_list = &hbp->iPtrs[0];		// one address...
       
   278 	hbp->iPtrs[0] = (char*)&hbp->iAddr.sa_data[0];	// ... which is iAddr
       
   279 
       
   280 	TPtr8 tname((TText8*)&hbp->iName[0], name->Size()+1);
       
   281 	tname.Copy(name->Des());
       
   282 	tname.ZeroTerminate();
       
   283     delete name;
       
   284     
       
   285 	unsigned long len = sizeof(hbp->iAddr);
       
   286 	aRecord.iAddr.SetFamily(format);	// not set by GetByName(_L(""));
       
   287 	static_cast<TUSockAddr*>(&aRecord.iAddr)->Get(&hbp->iAddr, &len);	
       
   288 	return &hbp->iHostent;
       
   289 	}
       
   290 
       
   291 /*
       
   292 Get the internet name of the host by address.
       
   293 @return 
       
   294 @param rp pointer
       
   295 @param addr 
       
   296 @param length 
       
   297 @param format 
       
   298 */
       
   299 EXPORT_C struct hostent* _gethostbyaddr_r (struct _reent* rp, const char* addr, int length, int format)
       
   300 	{
       
   301 	TInt err = KErrNone;
       
   302 	struct hostent* retval = NULL;
       
   303 	
       
   304 	RSocketServ& ss = Backend()->SockServSession();
       
   305 	// connect to the Socket Server if necessary
       
   306 	if (ss.Handle() == 0)
       
   307 		{
       
   308 		err = SockServConnect(ss);
       
   309 		if (err != KErrNone)
       
   310 			{
       
   311 			MapError(err, rp->_errno);
       
   312 			return retval;
       
   313 			}
       
   314 		}
       
   315 	
       
   316     if(format != AF_INET && format != AF_INET6)
       
   317         {
       
   318         format = AF_INET;
       
   319         }
       
   320 	    
       
   321 	if (err == KErrNone)
       
   322 		{
       
   323 		RHostResolver r;
       
   324 		/* Get the default RConnection instance and use it if configured. 
       
   325 		   NOTE: This RConnection, if configured, would be created using the
       
   326 		   socket server on backend. The same server has to be used here */
       
   327 		RConnection defConnection = Backend()->GetDefaultConnection();
       
   328 		if(defConnection.SubSessionHandle() != 0)
       
   329 		    {
       
   330 			err=r.Open(ss, format, IPPROTO_UDP, defConnection);
       
   331 		    }
       
   332 		else
       
   333 		    {
       
   334 			err=r.Open(ss, format, IPPROTO_UDP);
       
   335 		    }
       
   336 		
       
   337 		if (err == KErrNone)
       
   338 			{
       
   339 			struct sockaddr buf;
       
   340 			buf.sa_family = (unsigned short)format;
       
   341 			memcpy(buf.sa_data,addr,length);
       
   342 			TUSockAddr addr(&buf, length+4);
       
   343 			TNameRecord record;
       
   344 			TNameEntry entry(record);
       
   345 		    TInetAddr inetAddr(addr);
       
   346 		    
       
   347             if(inetAddr.IsLoopback())
       
   348                 {
       
   349                 if(format == AF_INET)
       
   350                     inetAddr.SetAddress(KInetAddrLoop);
       
   351                 else if(format == AF_INET6)
       
   352                     inetAddr.SetAddress(KInet6AddrLoop);
       
   353                 entry().iAddr = inetAddr;
       
   354                 entry().iName.Copy(_L("localhost"));
       
   355                 }
       
   356 		            
       
   357             else
       
   358                 {
       
   359                 err = r.GetByAddress(addr, entry);
       
   360                 while (err == KErrNone)
       
   361                     {
       
   362                     TInetAddr addr(entry().iAddr);
       
   363                     if(!addr.IsUnspecified())
       
   364                         {
       
   365                         if(format == addr.Family())
       
   366                             {
       
   367                             break;
       
   368                             }
       
   369                         else if(format == AF_INET && addr.Family() == AF_INET6 && addr.IsV4Mapped())
       
   370                             {
       
   371                             addr.ConvertToV4();
       
   372                             entry().iAddr = addr;
       
   373                             break;
       
   374                             }
       
   375                         }
       
   376                     err = r.Next(entry);
       
   377                     }
       
   378                 }
       
   379 		             if (err == KErrNone)
       
   380 		                {
       
   381 		                record = entry();
       
   382 		                retval = mapNameRecord(rp, record, length, format);
       
   383 		                }
       
   384 			r.Close();
       
   385 			}
       
   386 		}
       
   387 	if (err == -3004)	// NETDIAL busy
       
   388 		err = TRY_AGAIN;
       
   389 	if (err < -3000)	// i.e. a NETDIAL error
       
   390 		err = NO_RECOVERY;
       
   391 	MapError(err, rp->_errno);
       
   392 	return retval;
       
   393 	}
       
   394 
       
   395 /*
       
   396 Get the internet name of the host by name.
       
   397 @return 
       
   398 @param rp 
       
   399 @param name name of the host
       
   400 */
       
   401 EXPORT_C struct hostent* _gethostbyname_r (struct _reent* rp, const char* name)
       
   402 	{
       
   403 	TInt err = KErrNone;
       
   404 	struct hostent* retval = NULL;
       
   405 	RSocketServ& ss = Backend()->SockServSession();
       
   406 	// connect to the Socket Server if necessary
       
   407 	if (ss.Handle() == 0)
       
   408 		{
       
   409 		err = SockServConnect(ss);
       
   410 		if (err != KErrNone)
       
   411 			{
       
   412 			MapError(err, rp->_errno);
       
   413 			return retval;
       
   414 			}
       
   415 		}
       
   416 	
       
   417     RHostResolver r;
       
   418     /* Get the default RConnection instance and use it if configured. 
       
   419        NOTE: This RConnection, if configured, would be created using the
       
   420        socket server on backend. The same server has to be used here */
       
   421     RConnection defConnection = Backend()->GetDefaultConnection();
       
   422     if (defConnection.SubSessionHandle() != 0)
       
   423         {
       
   424         err = r.Open(ss, AF_INET, IPPROTO_UDP, defConnection);
       
   425         }
       
   426     else
       
   427         {
       
   428         err = r.Open(ss, AF_INET, IPPROTO_UDP);
       
   429         }
       
   430     
       
   431     if (err == KErrNone)
       
   432         {
       
   433         TNameRecord record;
       
   434         TNameEntry entry(record);
       
   435         
       
   436         TPtrC8 ptr(reinterpret_cast<const TUint8*> (name));
       
   437         THostName hostname;
       
   438         hostname.Copy(ptr);
       
   439         
       
   440         if (hostname.CompareF(_L("localhost")) == KErrNone)
       
   441             {
       
   442             TInetAddr addr;
       
   443             addr.SetAddress(KInetAddrLoop);
       
   444             entry().iAddr = addr;
       
   445             entry().iName.Copy(hostname);
       
   446             }
       
   447         else
       
   448             {
       
   449             err = r.GetByName(hostname, entry);
       
   450             while (err == KErrNone)
       
   451                 {
       
   452                 TInetAddr addr(entry().iAddr);
       
   453                 if(!addr.IsUnspecified())
       
   454                     {
       
   455                     if (addr.Family() == KAfInet) 
       
   456                         {
       
   457                         break;
       
   458                         }
       
   459                     
       
   460                     if (addr.Family() == KAfInet6 && (addr.IsV4Compat() || addr.IsV4Mapped()))
       
   461                         {
       
   462                         addr.ConvertToV4(); 
       
   463                         entry().iAddr = addr;
       
   464                         break;
       
   465                         }
       
   466                     }
       
   467                 err = r.Next(entry);
       
   468                 }
       
   469             }
       
   470         
       
   471         if (err == KErrNone)
       
   472             {
       
   473             record = entry();
       
   474             retval = mapNameRecord(rp, record, sizeof(struct in_addr), AF_INET);
       
   475             }
       
   476         
       
   477         r.Close();
       
   478         }
       
   479 
       
   480 	if (err == -3004)	// NETDIAL busy
       
   481 		err = TRY_AGAIN;
       
   482 	if (err < -3000)	// i.e. a NETDIAL error
       
   483 		err = NO_RECOVERY;
       
   484 	MapError(err, rp->_errno);
       
   485 	return retval;
       
   486 	}
       
   487 
       
   488 /*
       
   489  * Set the default IAP interface in the backend
       
   490  * @param	aErrno 	The errno to be set
       
   491  * @param	aIfReq	Pointer to the ifreq structure containing the interface name
       
   492  * @return 			0 on success, -1 on failure 
       
   493  */
       
   494 EXPORT_C int _setdefaultif_r(int *aErrno, const struct ifreq* aIfReq)
       
   495 	{
       
   496 	TInt err = KErrNone;
       
   497 
       
   498 	RSocketServ& ss = Backend()->SockServSession();
       
   499 	// connect to the Socket Server if necessary
       
   500 	//NOTE: The following is not really threadsafe. The checking for the 
       
   501 	//server handle and connecting to the same should be atomic, and should
       
   502 	//be done everywhere else too
       
   503 	if (ss.Handle() == 0)
       
   504 		{
       
   505 		err = SockServConnect(ss);
       
   506 		if (err != KErrNone)
       
   507 			{
       
   508 			MapError(err, *aErrno);
       
   509 			return -1;
       
   510 			}
       
   511 		}
       
   512 	
       
   513 	err = Backend()->setdefaultif(aIfReq);
       
   514 	if(err != KErrNone)
       
   515 		{
       
   516 		MapError(err, *aErrno);
       
   517 		return -1;
       
   518 		}
       
   519 	
       
   520 	return 0;
       
   521 	}
       
   522 
       
   523 /*
       
   524  * Helper function to create an addrinfo node and fill it.
       
   525  * @param	aRec		 	The name details to be used to fill the addrinfo node
       
   526  * @param	aHints			The hints to be used
       
   527  * @param	aNode			Pointer to the addrinfo structure pointer to be created
       
   528  * @return 					0 on success, EAI_MEMORY on error 
       
   529  */
       
   530 static int CreateAddrInfoNode(TNameRecord& aRec, const struct addrinfo* aHints, struct addrinfo** aNode)
       
   531 	{
       
   532 	unsigned long addrLen = 0;
       
   533 	TUint nameLen = aRec.iName.Length();
       
   534 	
       
   535 	//The following alloc function fills the chunk with zeros
       
   536 	*aNode = (struct addrinfo*) Backend()->Alloc(sizeof(struct addrinfo));
       
   537 	if(*aNode == NULL)
       
   538 		return EAI_MEMORY;
       
   539 	
       
   540 	//Copy the canonical name
       
   541 	if(nameLen != 0 || (aHints->ai_flags & AI_CANONNAME)) 
       
   542 		{
       
   543 		(*aNode)->ai_canonname = (char*) Backend()->Alloc(nameLen + 1);
       
   544 		if((*aNode)->ai_canonname == NULL)
       
   545 			{
       
   546 			Backend()->Free(*aNode);
       
   547 			*aNode = NULL;
       
   548 			return EAI_MEMORY;
       
   549 			}
       
   550 		
       
   551 		TPtr8 namePtr((TText8*) (*aNode)->ai_canonname, nameLen + 1); 
       
   552 #ifdef _UNICODE
       
   553 		CnvUtfConverter::ConvertFromUnicodeToUtf8(namePtr, aRec.iName); //wchar* string
       
   554 #else	
       
   555 		namePtr.Copy(aRec.iName); //char* string
       
   556 #endif /* _UNICODE */
       
   557 		namePtr.ZeroTerminate();
       
   558 		}
       
   559 	
       
   560 	 TInetAddr inetAddr(aRec.iAddr);
       
   561 	 (*aNode)->ai_family = inetAddr.Family();
       
   562 	
       
   563 	//Copy the address
       
   564 	(*aNode)->ai_addr = (struct sockaddr*) Backend()->Alloc(sizeof(struct sockaddr));
       
   565 	if((*aNode)->ai_addr == NULL) 
       
   566 		{
       
   567 		if((*aNode)->ai_canonname != NULL)
       
   568 			Backend()->Free((*aNode)->ai_canonname);
       
   569 		Backend()->Free(*aNode);
       
   570 		*aNode = NULL;
       
   571 		return EAI_MEMORY;
       
   572 		}
       
   573 		
       
   574 	addrLen = sizeof((*aNode)->ai_addr);
       
   575 	STATIC_CAST(TUSockAddr*, &aRec.iAddr)->Get((*aNode)->ai_addr, &addrLen);
       
   576 	(*aNode)->ai_addrlen = addrLen;
       
   577 	
       
   578 	return 0;
       
   579 	}
       
   580 
       
   581 /*
       
   582  * Get the list of addresses (in the form of addrinfo structure) by 
       
   583  * resolving the given host name. This function returns only
       
   584  * the adresses and the canonical names
       
   585  * @param	aErrno		 	Pointer to errno
       
   586  * @param	aHostName		The host name to be resolved
       
   587  * @param	aHints			Pointer to the hints structure
       
   588  * @param	aRes			The pointer to store the result
       
   589  * @return 					0 on success, error code on failure
       
   590  */
       
   591 EXPORT_C int _getaddrinfo_r(int* aErrno, const char* aHostName, 
       
   592 							const struct addrinfo* aHints, struct addrinfo** aRes)
       
   593 	{
       
   594 	TInt err = KErrNone;
       
   595 	
       
   596 	//Check params
       
   597 	if(!aHostName || !aHints || !aRes)
       
   598 		return EAI_FAIL;
       
   599 	
       
   600 #ifdef _UNICODE
       
   601 	TPtrC8 hNamePtr(REINTERPRET_CAST(const TUint8*, aHostName));
       
   602 	TBuf<0x40> hostName;
       
   603 	hostName.Copy(hNamePtr);
       
   604 #else
       
   605 	TPtrC8 hostName(REINTERPRET_CAST(const TUint8*, aHostName));
       
   606 #endif /* _UNICODE */
       
   607 	
       
   608 	//Check for 'localhost'.
       
   609     TBuf<64> localHostName;
       
   610     _LIT(KNameBuf, "localhost");
       
   611     localHostName.Copy(KNameBuf);
       
   612 	if(hostName.CompareF(localHostName) == 0 && aHints->ai_family == AF_INET)
       
   613 		{
       
   614 		TInetAddr localAddr;
       
   615 		TNameRecord nameRec;
       
   616 		localAddr.SetAddress(INET_ADDR(127, 0, 0, 1));
       
   617 		nameRec.iAddr = localAddr;
       
   618 		nameRec.iName.Copy(localHostName);
       
   619 		
       
   620 		return CreateAddrInfoNode(nameRec, aHints, aRes); 
       
   621 		}
       
   622 	
       
   623     // connect to the Socket Server if necessary
       
   624 	RSocketServ& sockServ = Backend()->SockServSession();
       
   625 	if (sockServ.Handle() == 0)
       
   626 		{
       
   627 		err = SockServConnect(sockServ);
       
   628 		if (err != KErrNone)
       
   629 			{
       
   630 			MapError(err, *aErrno);
       
   631 			return EAI_SYSTEM;
       
   632 			}
       
   633 		}
       
   634 	
       
   635 	//Open the host resolver
       
   636 	RHostResolver resolver;
       
   637 	/* Get the default RConnection instance and use it if configured. 
       
   638 	   NOTE: This RConnection, if configured, would be created using the
       
   639 	   socket server on backend. The same server has to be used here */
       
   640 	RConnection defConnection = Backend()->GetDefaultConnection();
       
   641 	if(defConnection.SubSessionHandle() != 0)
       
   642 		err = resolver.Open(sockServ, KAfInet, KProtocolInetUdp, defConnection);
       
   643 	else
       
   644 		err = resolver.Open(sockServ, KAfInet, KProtocolInetUdp);
       
   645 	
       
   646 	if (err != KErrNone)
       
   647 		{
       
   648 		MapError(err, *aErrno);
       
   649 		return EAI_SYSTEM;
       
   650 		}
       
   651 	
       
   652 	//Resolve by name
       
   653 	TNameRecord nameRec;
       
   654 	TNameEntry nameEntry(nameRec);
       
   655 
       
   656 	err = resolver.GetByName(hostName, nameEntry);
       
   657 	if( err != KErrNone)
       
   658 		{
       
   659 		resolver.Close();
       
   660 		return EAI_FAIL; 
       
   661 		}
       
   662 	
       
   663 	//Create a list of addrinfo nodes from the result
       
   664 	*aRes = NULL;
       
   665 	struct addrinfo** curr = aRes;
       
   666 	  do
       
   667 	        {
       
   668 	        nameRec = nameEntry();
       
   669 	        TInetAddr inetAddr(nameRec.iAddr);
       
   670 	        //Create the node if the address is valid, and the family matches that of hints
       
   671 	        if(!inetAddr.IsUnspecified())
       
   672 	            {
       
   673 	            if (inetAddr.Family() == KAfInet)
       
   674 	                {
       
   675 	                err = CreateAddrInfoNode(nameRec, aHints, curr);
       
   676 	                }
       
   677 	            else if (inetAddr.Family() == KAfInet6)
       
   678 	                {
       
   679 	                err = CreateAddrInfoNode(nameRec, aHints, curr);
       
   680 	                if (err != 0)
       
   681 	                    break;
       
   682 	                
       
   683 	                curr = &((*curr)->ai_next);
       
   684 	                if (inetAddr.IsV4Mapped())
       
   685 	                    {
       
   686 	                    inetAddr.ConvertToV4();
       
   687 	                    nameRec.iAddr = inetAddr;
       
   688 	                    err = CreateAddrInfoNode(nameRec, aHints, curr);
       
   689 	                    
       
   690 	                    if(err != 0)
       
   691 	                        break;
       
   692 	                    
       
   693 	                    if (err == 0)
       
   694 	                        {
       
   695 	                        (*curr)->ai_flags |= AI_V4MAPPED;
       
   696 	                        curr = &((*curr)->ai_next);
       
   697 	                        }
       
   698 	                    }
       
   699 	                }
       
   700 	            }
       
   701 	        err = resolver.Next(nameEntry); //Get the next record
       
   702 	        if(err != KErrNone)
       
   703 	            {//No more records. Not an error, just stop iterating
       
   704 	            err = KErrNone;
       
   705 	            break;
       
   706 	            }
       
   707 	        } while(err == KErrNone);
       
   708 	       
       
   709 	
       
   710 	//If no nodes are created even when the operation is succes, it's an error
       
   711 	if(err == 0 && *aRes == NULL)
       
   712 		err = -1;
       
   713 	//If the operation failed and some nodes are created, free them
       
   714 	if(err != 0 && *aRes != NULL)
       
   715 		{		
       
   716 		_freeaddrinfo_r(*aRes);
       
   717 		*aRes = NULL;
       
   718 		}
       
   719 	if(err != 0 && err != EAI_MEMORY)
       
   720         err = EAI_FAIL;
       
   721 	resolver.Close();
       
   722 	return err;
       
   723 	}
       
   724 
       
   725 /*
       
   726  * Frees the addrinfo structure created in backend
       
   727  * @param	aInfo	The pointer to the addrinfo structure to be freed 
       
   728  */
       
   729 EXPORT_C void _freeaddrinfo_r(struct addrinfo* aInfo)
       
   730 	{
       
   731 	if(aInfo == NULL)
       
   732 		return;
       
   733 	
       
   734 	struct addrinfo *next;
       
   735 	while(aInfo)
       
   736 		{
       
   737 		next = aInfo->ai_next;
       
   738 		if(aInfo->ai_canonname != NULL)
       
   739 			Backend()->Free(aInfo->ai_canonname);
       
   740 		if(aInfo->ai_addr != NULL)
       
   741 			Backend()->Free(aInfo->ai_addr);
       
   742 		
       
   743 		Backend()->Free(aInfo);
       
   744 		aInfo = next;
       
   745 		} 
       
   746 	}
       
   747 
       
   748 } //extern "C"