os/ossrv/genericopenlibs/cstdlib/LPOSIX/NETDB.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // Support for hostname & hostaddr related functions
    15 // 
    16 //
    17 
    18 #include "SYSIF.H"
    19 #include "FDESC.H"
    20 #include <unistd.h>
    21 #include <stdlib.h>
    22 #include <sys/errno.h>
    23 #include "LPOSIX.H"
    24 #include <sys/socket.h>
    25 #include <libc/netinet/in.h>
    26 #include <netdb_r.h>
    27 #include <string.h>
    28 #include <in_sock.h>
    29 #include <networking/dnd_err.h>
    30 
    31 extern "C" {
    32 
    33 /**
    34 Get the internet name of this host. Actually this will always return a null 
    35 string with TCPIP 030 and onwards because the "name" of a mobile host
    36 isn't really very meaningful - in practice the IP address is chosen dynamically
    37 once you start doing real networking, at which time the ISP can resolve the 
    38 IP address into a name of some sort if you really want.
    39 @return 
    40 @param name
    41 @param size
    42 */
    43 EXPORT_C int gethostname (char *name, size_t size)
    44 	{
    45 	int* perrno=__errno();
    46 	RSocketServ ss;
    47 	TInt err=ss.Connect(1);
    48 	if (err==KErrNone)
    49 		{
    50 		RHostResolver r;
    51 		err=r.Open(ss, AF_INET, KProtocolInetUdp);
    52 		if (err==KErrNone)
    53 			{
    54 			TBuf<128> hostname;
    55 			err=r.GetHostName(hostname);
    56 			if (err==KErrNone)
    57 				{
    58 				if (size>(size_t)hostname.Length())
    59 					{
    60 					TPtr8 retval((TText8*)name,size);
    61 					retval.Copy(hostname);
    62 					retval.PtrZ();
    63 					}
    64 				else
    65 					err=ENAMETOOLONG;
    66 				}
    67 			r.Close();
    68 			}
    69 		ss.Close();
    70 		}
    71 	return MapError(err,*perrno);
    72 	}
    73 
    74 /**
    75 Get the internet name of the host by address.
    76 @return 
    77 @param addr Address of the host
    78 @param length 
    79 @param format 
    80 */
    81 EXPORT_C struct hostent* gethostbyaddr (const char* addr, int length, int format)
    82 	{
    83 	return _gethostbyaddr_r(_REENT,addr,length,format);
    84 	}
    85 
    86 /**
    87 Get the internet name of the host by name.
    88 @return 	
    89 @param name Name of the host
    90 */
    91 EXPORT_C struct hostent* gethostbyname (const char* name)
    92 	{
    93 	return _gethostbyname_r(_REENT,name);
    94 	}
    95 
    96 enum GetHostType {ByName = 1, ByAddr};
    97 
    98 #define MAX_ADDR_OR_ALIAS_LIST	5
    99 
   100 struct hostent_buf
   101 	{
   102 	struct hostent iHostent;
   103 	char *iAliasesPtr[MAX_ADDR_OR_ALIAS_LIST+1];
   104 	char *iAddrListPtr[MAX_ADDR_OR_ALIAS_LIST+1];
   105 	THostName iHostAliases[MAX_ADDR_OR_ALIAS_LIST];
   106 	struct sockaddr iHostAddress[MAX_ADDR_OR_ALIAS_LIST];
   107 	};
   108 
   109 struct hostent* mapNameRecord(struct _reent* rp, TFixedArray<TNameRecord, MAX_ADDR_OR_ALIAS_LIST>& aRecord, const TInt aCount, const GetHostType aHostType, const int aLength, const int aFormat)
   110 	{
   111 	free(rp->_netdb);
   112 	struct hostent_buf* hbp = (struct hostent_buf*)calloc(1,sizeof(struct hostent_buf));
   113 	rp->_netdb = hbp;
   114 	if (hbp==0)
   115 		{
   116 		rp->_errno=ENOMEM;
   117 		return 0;
   118 		}
   119 
   120 	// Set-up Aliases & Address list pointer
   121 	hbp->iHostent.h_aliases = &hbp->iAliasesPtr[0];
   122 	hbp->iHostent.h_addr_list = &hbp->iAddrListPtr[0];
   123 
   124 	// Fill-up Host Name
   125 	hbp->iHostent.h_name = (char*) &hbp->iHostAliases[0];
   126 	TPtr8 name((TText8*)&hbp->iHostAliases[0], aRecord[0].iName.Length()+1);
   127 	name.Copy(aRecord[0].iName);
   128 	name.ZeroTerminate();
   129 
   130 	hbp->iHostent.h_addrtype = aFormat;
   131 	hbp->iHostent.h_length = aLength;
   132 
   133 	// Fill-up Address
   134 	hbp->iAddrListPtr[0] = (char*)&hbp->iHostAddress[0].sa_data[0];		// ... which is iAddr
   135 	unsigned long len=sizeof(struct sockaddr);
   136 	aRecord[0].iAddr.SetFamily(aFormat);	// not set by GetByName(_L(""));
   137 	STATIC_CAST(TUSockAddr*,&aRecord[0].iAddr)->Get(&hbp->iHostAddress[0],&len);
   138 
   139 	if (aCount > 1)
   140 		{
   141 		// If there are multiple host name or address
   142 		TInt i;
   143 		if (aHostType == ByName)
   144 			{
   145 			// there are multiple addresses for a given host
   146 			hbp->iAliasesPtr[0] = NULL;
   147 			for (i=1; i<aCount; i++)
   148 				{
   149 				hbp->iAddrListPtr[i] = (char*)&hbp->iHostAddress[i].sa_data[0];
   150 				len=sizeof(struct sockaddr);
   151 				aRecord[i].iAddr.SetFamily(aFormat);	// not set by GetByName(_L(""));
   152 				STATIC_CAST(TUSockAddr*,&aRecord[i].iAddr)->Get(&hbp->iHostAddress[i],&len);
   153 				}
   154 			hbp->iAddrListPtr[i] = NULL;
   155 			}
   156 		else
   157 			{
   158 			// there are multiple host/aliases name for a given address
   159 			hbp->iAddrListPtr[1] = NULL;
   160 			for (i=1; i<aCount; i++)
   161 				{
   162 				hbp->iAliasesPtr[i-1] = (char*) &hbp->iHostAliases[i];
   163 				name.Set((TText8*)&hbp->iHostAliases[i], 0, aRecord[i].iName.Length()+1);
   164 				name.Copy(aRecord[i].iName);
   165 				name.ZeroTerminate();
   166 				}
   167 			hbp->iAliasesPtr[i-1] = NULL;
   168 			}
   169 		}
   170 	else
   171 		{
   172 		hbp->iAliasesPtr[0] = NULL;
   173 		hbp->iAddrListPtr[1] = NULL;
   174 		}
   175 	return &hbp->iHostent;
   176 	}
   177 
   178 /**
   179 Get the internet name of the host by address.
   180 @return 
   181 @param rp pointer
   182 @param addr 
   183 @param length 
   184 @param format 
   185 */
   186 EXPORT_C struct hostent* _gethostbyaddr_r (struct _reent* rp, const char* addr, int length, int format)
   187 //
   188 // For AF_INET, 
   189 	{
   190 	RSocketServ ss;
   191 	TInt err=ss.Connect();
   192 	struct hostent* retval=0;
   193 	if (err==KErrNone)
   194 		{
   195 		RHostResolver r;
   196 		err=r.Open(ss, AF_INET, KProtocolInetUdp);
   197 		if (err==KErrNone)
   198 			{
   199 			struct sockaddr buf;
   200 			buf.sa_family=(unsigned short)format;
   201 			memcpy(buf.sa_data,addr,length);
   202 			TUSockAddr addr(&buf,length+4);
   203 
   204 			TFixedArray<TNameRecord, MAX_ADDR_OR_ALIAS_LIST> record;
   205 			TNameEntry entry;
   206 			TInt count = 0;
   207 			err=r.GetByAddress(addr,entry);
   208 			if (err==KErrNone)
   209 				{
   210 				record[count++]=entry();
   211 				while ((r.Next(entry) == KErrNone) && (count < MAX_ADDR_OR_ALIAS_LIST))
   212 					{
   213 					record[count++] = entry();
   214 					}
   215 				retval = mapNameRecord(rp, record, count, ByAddr, length, format);
   216 				}
   217 			r.Close();
   218 			}
   219 		ss.Close();
   220 		}
   221 	if (err==-3004)	// NETDIAL busy
   222 		err=TRY_AGAIN;
   223 
   224 	// KErrDndAddrNotFound=-5121 should be excluded (Returned when no data found for GetByAddr)
   225 	if ((err<-3000)	&& (err!=KErrDndAddrNotFound))	// i.e. a NETDIAL error
   226 		err=NO_RECOVERY;
   227 	MapError(err,rp->_errno);
   228 	return retval;
   229 	}
   230 
   231 /**
   232 Get the internet name of the host by name.
   233 @return 
   234 @param rp 
   235 @param name name of the host
   236 */
   237 EXPORT_C struct hostent* _gethostbyname_r (struct _reent* rp, const char* name)
   238 	{
   239 	RSocketServ ss;
   240 	TInt err=ss.Connect();
   241 	struct hostent* retval=0;
   242 	if (err==KErrNone)
   243 		{
   244 		RHostResolver r;
   245 		err=r.Open(ss, AF_INET, KProtocolInetUdp);
   246 		if (err==KErrNone)
   247 			{			
   248 			TFixedArray<TNameRecord, MAX_ADDR_OR_ALIAS_LIST> record;
   249 			TNameEntry entry;
   250 #ifdef _UNICODE
   251 			TPtrC8 ptr(REINTERPRET_CAST(const TUint8*,name));
   252 			TBuf<0x40> hostname;
   253 			hostname.Copy(ptr);
   254 #else
   255 			TPtrC8 hostname(REINTERPRET_CAST(const TUint8*,name));
   256 #endif /* _UNICODE */
   257 
   258 			TInt count = 0;
   259 			err=r.GetByName(hostname,entry);
   260 			if (err==KErrNone)
   261 				{
   262 				record[count++]=entry();
   263 				while ((r.Next(entry) == KErrNone) && (count < MAX_ADDR_OR_ALIAS_LIST))
   264 					{
   265 					record[count++] = entry();
   266 					}
   267 				retval = mapNameRecord(rp, record, count, ByName, sizeof(struct in_addr), AF_INET);
   268 				}
   269 			r.Close();
   270 			}
   271 		ss.Close();
   272 		}
   273 	if (err==-3004)	// NETDIAL busy
   274 		err=TRY_AGAIN;
   275 
   276 	// KErrDndNameNotFound=-5120 should be excluded (Returned when no data found for GetByName)
   277 	if ((err<-3000)	&& (err!=KErrDndNameNotFound)) // i.e. a NETDIAL error
   278 		err=NO_RECOVERY;
   279 	MapError(err,rp->_errno);
   280 	return retval;
   281 	}
   282 
   283 } // extern "C"