genericopenlibs/cstdlib/LPOSIX/NETDB.CPP
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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"